Node.js dns.resolve() 对比 dns.lookup()

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

我需要在 Node.js 中查找给定主机到其对应的 IP。似乎有两种本机方法可以执行此操作:

> 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

两者 return 相同的 IPv4 地址。 dns.lookup()dns.resolve() 有什么区别?另外,对于每秒大量请求,哪个性能更高?

dns documentation已经描述了区别:

Although dns.lookup() and the various dns.resolve*()/dns.reverse() functions have the same goal of associating a network name with a network address (or vice versa), their behavior is quite different. These differences can have subtle but significant consequences on the behavior of Node.js programs.

dns.lookup()
Under the hood, dns.lookup() uses the same operating system facilities as most other programs. For instance, dns.lookup() will almost always resolve a given name the same way as the ping command. On most POSIX-like operating systems, the behavior of the dns.lookup() function can be modified by changing settings in nsswitch.conf(5) and/or resolv.conf(5), but note that changing these files will change the behavior of all other programs running on the same operating system.

Though the call to dns.lookup() will be asynchronous from JavaScript's perspective, it is implemented as a synchronous call to getaddrinfo(3) that runs on libuv's threadpool. Because libuv's threadpool has a fixed size, it means that if for whatever reason the call to getaddrinfo(3) takes a long time, other operations that could run on libuv's threadpool (such as filesystem operations) will experience degraded performance. In order to mitigate this issue, one potential solution is to increase the size of libuv's threadpool by setting the 'UV_THREADPOOL_SIZE' environment variable to a value greater than 4 (its current default value). For more information on libuv's threadpool, see the official libuv documentation.

dns.resolve(), dns.resolve*() and dns.reverse()
These functions are implemented quite differently than dns.lookup(). They do not use getaddrinfo(3) and they always perform a DNS query on the network. This network communication is always done asynchronously, and does not use libuv's threadpool.

As a result, these functions cannot have the same negative impact on other processing that happens on libuv's threadpool that dns.lookup() can have.

They do not use the same set of configuration files than what dns.lookup() uses. For instance, they do not use the configuration from /etc/hosts.

并发性 而言,您最好使用 dns.resolve*() 因为这些请求不会在线程池中结束,而 dns.lookup() 请求do 因为他们调用通常会阻塞的 OS DNS 解析器(尽管现在有某种异步接口——但它们不一定在所有地方都实现)。

目前,节点在内部使用 dns.lookup() 进行任何自动 DNS 解析,例如将主机名传递给 http.request()

@mscdex 的回答真的很完整,而且解释得很清楚。我可能会添加有关我们用来绕过线程阻塞的方法的信息。

我们开发了一个 replaces/extends 节点的 dns.lookup 方法的模块。模块缓存响应,具有多记录解析和 TTL 支持。我们也有很好的单位和功能 tests with 100% coverage. Module was tested in production and highload environments. Under MIT license. Here it is: https://github.com/LCMApps/dns-lookup-cache

如果您需要查找方法的支持,但又不会产生负面影响,例如应用程序阻塞或响应变慢,您可以使用我们的模块。我相信它会有所帮助!