为什么libuv做多个线程的DNS请求

有时候我的服务一直发送大的差异主机名url,我会重新构build我的docker容器,容器同时重启,有些http请求会失败:

events.js:154 throw er; // Unhandled 'error' event ^ Error: getaddrinfo ENOTFOUND www.videojj.com www.videojj.com:80 at errnoException (dns.js:26:10) at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:77:26) 

我不知道是什么原因,我知道DNS,由libuv中的multithreading文件操作。 我很困惑为什么DNS请求不能在libuv中使用IO多路复用机制

正如你所提到的,根据文件 (重点是我的):

libuv提供了一个线程池,可以用来运行用户代码并在循环线程中得到通知。 此线程池在内部用于运行所有文件系统操作,以及getaddrinfo和getnameinfo请求

uvbook给出了一些其他的提示:

线程在内部使用来伪造所有系统调用的asynchronous特性。 libuv还使用线程来允许您(应用程序)通过产生线程并在完成时收集结果来asynchronous执行实际阻塞的任务。

所以,回到你的问题:

为什么DNS请求不能在libuv中使用IO多路复用机制

这是由于fs操作和(让我说) DNS请求阻止系统调用。 因此,他们将击败libuv的asynchronous性质,并强制循环在主线程上执行。 没有办法,只能在一个单独的线程上启动它们,以保持循环运行,直到工作完成。

请注意,也存在getaddrinfogetnameinfo非阻塞版本,但它们不可移植,因此libuv无法一直使用它们。
在SO上看到这个问题了解更多细节。

也许,在发送请求之前,我们需要知道主机IP地址,因此,发送请求和DNS请求必须同步,因为libuv中的IO多路复用工作在主线程上,将同步操作放在上面是愚蠢的主线程,所以DNS请求使用线程池。