>  기사  >  웹 프론트엔드  >  Nodejs의 DNS 캐싱 문제에 대한 간략한 분석

Nodejs의 DNS 캐싱 문제에 대한 간략한 분석

高洛峰
高洛峰원래의
2016-12-06 15:44:461824검색

우연히 nodejs에서 http 요청을 보내면 DNS 결과가 캐시되지 않는다는 기사를 보았습니다. 이는 nodejs를 기반으로 http 수집 프로그램을 작성하는 경우 DNS 캐싱을 제공하지 않으면 각 요청이 어리석게도 도메인 이름을 IP 주소로 반복적으로 확인한다는 의미입니다. 성능에 많은 영향을 미칠 것 같죠?

내 프로젝트에서 http 요청을 보내는 것은 노드의 기본 http 라이브러리를 사용하지 않고 일반적으로 사용되는 요청 라이브러리에 의존합니다. 라이브러리의 관련 문서와 github 이슈를 살펴보니 dns 관련 게시물도 몇 개 발견되었습니다. 하지만 대부분의 사람들은 dns 문제 자체가 Request 라이브러리의 범위에 속하지 않고 nodejs의 핵심 문제에 기인한다고 말합니다. 맙소사, 정말 심오한 느낌이에요!

다행히 위에서 언급한 기사에서는 두 가지 솔루션도 제안했습니다.

애플리케이션 수준: dnscache

OS 수준: Bind, dnsmasq 및 unbound

어느 쪽이든 상관 없음 선택한 솔루션은 매우 간단해 보입니다. 그냥 설치하고 초기화하면 됩니다. 하지만 문제는 그것이 실제적이고 효과적인지 어떻게 확인할 수 있는가 하는 것입니다. 내 로컬 개발 컴퓨터 운영 체제 환경은 win7 64bit이므로 위에서 언급한 운영 체제 수준 솔루션을 테스트할 수 없습니다. 그럼 애플리케이션 레벨 솔루션이 효과적인지 살펴보겠습니다~~

우선 DNS 요청을 추적하려면 win을 활성화해야 합니다. 여기서는 다운로드 후 설치 없이 바로 실행할 수 있는 소프트웨어를 찾았습니다. 그런 다음 캐시를 지우는 방법도 필요합니다. 간단히 말하면 터미널에서 실행하세요.

ipconfig /flushdns

도구가 준비되었습니다.

const Request = require('request');
function fetch(url, callback){
Request.head({
url: url,
timeout: 10000,
tunnel: true,
gzip: true,
proxy: false,
followRedirect: false
}, callback);
}
let now = Date.now();
fetch('http://blog.kazaff.me', function(err, response, body){
console.log('lookup time without cache: ', Date.now() - now);
});

이제 DNSQuerySniffer를 열고 먼저 로컬 DNS 캐시를 정리한 후 테스트를 실행하세요. 모든 것이 준비되면 스크립트 nodetest.js. DNSQuerySniffer에서 DNS 요청 및 관련 정보를 볼 수 있습니다. 특정 시간 간격 내에 테스트 스크립트를 반복적으로 실행하면 DNS 요청이 다시 트리거되지 않는다는 것을 알 수 있습니다. 이것은 무엇을 의미합니까? 내 win7 환경 자체에는 운영 체제 수준의 DNS 캐시가 제공됩니다(그러나 캐시 시간은 매우 짧습니다).

다음과 같이 테스트 스크립트를 수정합니다.

이번에는 테스트 스크립트를 실행한 후 로컬 DNS 캐시를 빠르게 지웁니다(빠르지 않으면 setTimeout의 트리거 간격을 적절하게 연장할 수 있음), 2초 후에 http 요청이 DNS를 다시 쿼리하지 않는다는 것을 알 수 있습니다. 이것이 의미하는 바는 무엇입니까? 분명히 우리 애플리케이션은 자체 DNS 캐시를 유지하므로 두 번째 요청에서는 해당 DNS 캐시 레코드가 운영 체제에 로컬로 존재하는지 여부를 신경 쓰지 않습니다.
const dnscache = require('dnscache')({
"enable": true
});
const Request = require('request');
function fetch(url, callback){
Request.head({
url: url,
timeout: 10000,
tunnel: true,
gzip: true,
proxy: false,
followRedirect: false
}, callback);
}
let now = Date.now();
fetch('http://priceline.com', function(err, response, body){
console.log('lookup time without cache: ', Date.now() - now);
setTimeout(function(){
now = Date.now();
fetch('http://priceline.com', function(err, response, body){
console.log('lookup time with cache: ', Date.now() - now);
});
}, 2000);
});

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.