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

时间:2016-12-05 23:40:09

标签: javascript node.js dns ipv6 ipv4

我需要在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

两者都返回相同的IPv4地址。 dns.lookup()dns.resolve()之间有什么区别?此外,每秒钟的大量请求更能发挥作用吗?

2 个答案:

答案 0 :(得分:14)

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的线程池上运行的其他操作(例如文件系统操作)将经历性能下降。为了缓解这个问题,一个可能的解决方案是通过设置' UV_THREADPOOL_SIZE'来增加libuv的线程池的大小。环境变量大于4的值(其当前默认值)。有关libuv的线程池的更多信息,请参阅官方libuv文档。

dns.resolve(),dns.resolve *()和dns.reverse()
这些函数的实现与dns.lookup()完全不同。他们不使用getaddrinfo(3),他们总是在网络上执行DNS查询。此网络通信始终是异步完成的,不使用libuv的线程池。

因此,这些函数不会对dns.lookup()可以在libuv的线程池上发生的其他处理产生相同的负面影响。

它们不使用与dns.lookup()使用相同的配置文件集。例如,他们不使用/ etc / hosts中的配置。

并发而言,最好使用dns.resolve*(),因为这些请求不会在线程池中结束,而dns.lookup()请求执行< / em>因为他们呼叫通常阻塞的OS DNS解析器(虽然现在有某种异步接口 - 但它们并不一定在所有地方实现)。

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

答案 1 :(得分:0)

@mscdex答案确实很完整,并且可以解释。我可能会添加有关我们用来绕过线程阻塞的方法的信息。

我们开发了一个替换/扩展节点的dns.lookup方法的模块。模块缓存响应,具有多记录解析和TTL支持。此外,我们还具有良好的单元和功能aws-dynamodb。模块已在生产和高负载环境中进行了测试。根据MIT许可。这里是:tests with 100% coverage

如果您需要支持查找方法,但不起作用,如阻止应用程序或响应速度变慢等负面影响,则可以使用我们的模块。我相信这会有所帮助!