우연히 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); });