2017-06-17 63 views
1

有時候,我的服務發送大量diffirence主機名的URL所有的時間做DNS請求,我將重新建立我的搬運工容器,該容器的同時重新啓動,一些HTTP請求將會失敗:爲什麼libuv由多個線程

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中的多線程文件操作。我很困惑,爲什麼DNS請求不能在libuv

回答

1

使用IO複用機制,就像你提到的,並根據documentation(重點煤礦):

libuv提供了一個可用於運行一個線程池用戶代碼並在循環線程中得到通知。 此線程池在內部用於運行所有文件系統操作,以及getaddrinfo和getnameinfo請求

uvbook提供有關其他一些提示:

線程在內部使用的所有系統調用的假異步特性。 libuv還使用線程來允許應用程序通過產生線程並在完成時收集結果來異步執行實際阻塞的任務。

所以,回到你的問題:

爲什麼DNS請求不能使用libuv IO複用機制

也正是由於這樣的事實,FS操作和(更我說)DNS請求阻止系統調用。因此,如果在主線程上執行,它們將擊敗libuv的異步特性並強制循環停頓。沒有辦法,只能在一個單獨的線程上啓動它們以保持循環運行,直到完成工作。

請注意,也存在getaddrinfogetnameinfo的非阻塞版本,但它們不可移植,因此libuv無法一直使用它們。
有關更多詳細信息,請參見this question

+0

thx爲你回覆,我只想知道爲什麼DNS請求是一個阻止操作。 – bugall

+0

@bugall你確實問過一些不同的東西。無論如何,它們在設計上是同步的,而且它們有異步的對應物(不幸的是不能移植)。 Libuv無能爲力,只能將它們放在線程上。就這樣。 – skypjack

+1

@bugall:至少在POSIX中,DNS的API被阻止。 (libuv試圖保持接近POSIX;在DNS的情況下,你可能甚至不能通過其他簡單的方式獲得異步性,而不是通過線程/進程)。 –

0

也許,我們需要在發送請求之前知道主機IP地址,因此,發送請求和DNS請求必須同步,因爲libuv中的IO多路複用工作在主線程上,放愚蠢主線程上的同步操作,所以DNS請求使用線程池。

相關問題