web-dev-qa-db-ja.com

Node.js dns.resolve()とdns.lookup()

Node.jsで対応するIPに特定のホストを検索する必要があります。これを行うには、2つのネイティブメソッドがあるようです。

_> dns.resolve('google.com', (error, addresses) => { console.error(error); console.log(addresses); });
QueryReqWrap {
  bindingName: 'queryA',
  callback: { [Function: asyncCallback] immediately: true },
  hostname: 'google.com',
  oncomplete: [Function: onresolve],
  domain:
   Domain {
     domain: null,
     _events: { error: [Function] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
> null
[ '216.58.194.174' ]
_

そして:

_> dns.lookup('google.com', (error, address, family) => { console.error(error); console.log(address); console.log(family); });
GetAddrInfoReqWrap {
  callback: { [Function: asyncCallback] immediately: true },
  family: 0,
  hostname: 'google.com',
  oncomplete: [Function: onlookup],
  domain:
   Domain {
     domain: null,
     _events: { error: [Function] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
> null
216.58.194.174
4
_

どちらも同じIPv4アドレスを返します。 dns.lookup()dns.resolve()の違いは何ですか?また、1秒あたりのリクエスト数が多い場合、どちらがよりパフォーマンスが高くなりますか?

15
Justin

dns documentation はすでに違いを説明しています:

Dns.lookup()とさまざまなdns.resolve *()/ dns.reverse()関数には、ネットワーク名をネットワークアドレスに関連付ける(またはその逆)という同じ目的がありますが、動作はまったく異なります。これらの違いは、Node.jsプログラムの動作に微妙ですが重大な結果をもたらす可能性があります。

dns.lookup()
内部的には、dns.lookup()は他のほとんどのプログラムと同じオペレーティングシステム機能を使用しています。たとえば、dns.lookup()は、ほとんどの場合、pingコマンドと同じ方法で特定の名前を解決します。ほとんどのPOSIX系のオペレーティングシステムでは、nsswitch.conf(5)やresolv.conf(5)の設定を変更することにより、dns.lookup()関数の動作を変更できますが、これらのファイルを変更すると、同じオペレーティングシステムで実行されている他のすべてのプログラムの動作。

dns.lookup()への呼び出しはJavaScriptの観点から非同期ですが、libuvのスレッドプールで実行されるgetaddrinfo(3)への同期呼び出しとして実装されます。 libuvのスレッドプールのサイズは固定されているため、何らかの理由でgetaddrinfo(3)の呼び出しに時間がかかる場合、libuvのスレッドプールで実行できる他の操作(ファイルシステム操作など)ではパフォーマンスが低下することになります。この問題を軽減するための1つの解決策は、「UV_THREADPOOL_SIZE」環境変数を4(現在のデフォルト値)より大きい値に設定して、libuvのスレッドプールのサイズを増やすことです。 libuvのスレッドプールの詳細については、公式のlibuvのドキュメントを参照してください。

dns.resolve()、dns.resolve *()およびdns.reverse()
これらの関数は、dns.lookup()とはまったく異なる方法で実装されます。それらはgetaddrinfo(3)を使用せず、常にネットワーク上でDNSクエリを実行します。このネットワーク通信は常に非同期で行われ、libuvのスレッドプールを使用しません。

その結果、これらの関数は、dns.lookup()が持つ可能性があるlibuvのスレッドプールで発生する他の処理に同じ悪影響を与えることはできません。

それらは、dns.lookup()が使用するものと同じ構成ファイルのセットを使用しません。たとえば、/ etc/hostsの設定は使用しません。

concurrencyに関する限り、dns.resolve*()を使用することをお勧めします。これらの要求はスレッドプールで終了しないため、dns.lookup()リクエストdoは、通常ブロックするOS DNSリゾルバーを呼び出します(ただし、現在、ある種の非同期インターフェイスがありますが、必ずしもどこにでも実装されているわけではありません)。

現在、ノードはホスト名をdns.lookup()に渡すときなど、自動DNS解決にhttp.request()を内部的に使用しています。

16
mscdex

@mscdexの答えは本当にいっぱいで説明しています。スレッドブロッキングをバイパスするために使用するアプローチに関する情報を追加する場合があります。

ノードのdns.lookupメソッドを置換/拡張するモジュールを開発しました。モジュールは応答をキャッシュし、複数レコードの解決とTTLサポートがあります。また、優れたユニットと機能 100%カバレッジでのテスト があります。モジュールは本番環境と高負荷環境でテストされました。MITライセンスの下。ここにあります: https://github.com/LCMApps/dns-lookup-cache

ルックアップメソッドのサポートが必要であるが、アプリケーションのブロックや応答速度の低下などの悪影響を及ぼさない場合は、モジュールを使用できます。私はそれが役立つと信じています!

0
WoZ