[英]Node.js: Relationship among http.Server, http.Agent, sockets, and http.request
根據文檔:
Node.js 為每個服務器維護多個連接以發出 HTTP 請求。 此功能允許透明地發出請求。
文檔進一步指定 Node 默認依賴http.globalAgent
發出請求,但您可以通過創建新的http.Agent
來使用自己的代理。 代理用於為 http 請求“池化套接字”。
我對這一切的解釋是,每次執行http.createServer
,默認情況下都會獲得多個套接字(大概這就是“連接”的意思)來發出 http 請求,並且這些套接字由http.globalAgent
匯集/管理。
我不清楚的是當您創建自己的http.Agent
時會發生什么。 Agent
是否只是“接管”以前由http.globalAgent
管理的http.globalAgent
? 或者您是否必須通過agent.createConnection
為您的新Agent
創建一個新套接字?
在相關說明中,如果我要在同一個節點進程中啟動兩個服務器並隨后發出 http 請求,例如
const server1 = http.createServer(function(req, res) {
res.end('Hello from server1');
}).listen(3000);
const server2 = http.createServer(function(req, res) {
res.end('Hello from server2');
}).listen(5000);
http.get('/someurl');
從哪個服務器發出請求? http.Agent
在這里發揮作用嗎?
甚至我也對此感到困惑,但最近我找到了答案。
代理和全局代理
代理是節點用來向新服務器發出請求的源。 在這里您可以發現 Agent 發出請求調用。 代理需要有主機、端口和一些其他自定義標頭(KeepAlive 等)來發送請求。 如果未指定代理,則 Node 默認使用 globalAgent。 從這里我們可以分析,大多數標題都是默認設置的。 這兩者都有助於發出請求,因此如果您的服務在 127.0.0.1:8080 上運行,則可以使用它們發出請求。
插座
正如您所提到的,套接字是連接,使用這些連接向給定服務器發出請求。 這些套接字由操作系統(比如 Linux)管理,它為每個套接字創建一個新的套接字處理程序。 然而,特定域的套接字列表在 Agent/globalAgent 中維護。 我們可以設置maxSockets 、 maxFreeSockets等。這些有助於我們檢查操作系統資源的使用情況。
當一個新的代理被創建時,它應該管理從它發出的請求的連接。 agent.createConnection 創建一個 TCP 套接字。 這里提到它返回net.socket,因此您可以使用事件在此套接字上偵聽任何流。
const server1 = http.createServer(function(req, res) {
res.end('Hello from server1');
}).listen(3000);
const server2 = http.createServer(function(req, res) {
res.end('Hello from server2');
}).listen(5000);
在此代碼中,創建了 2 個服務器,它們分別在 3000 和 5000 處偵聽。它們應為客戶端發出的請求提供服務。 這些與您提出的請求無關。 您可以在不創建服務器的情況下發出 get 請求。 您發出的所有請求都由代理處理,因此該行中的 get 方法
http.get('/someurl');
實際上使用了HttpAgent。
進一步閱讀:
Agent
為什么我們需要Agent
?
建立從一台主機到另一台主機的連接的過程涉及兩個端點之間的多個數據包交換,這可能非常耗時,尤其是對於多個小的 http 請求。 Agent
通過保持連接打開並重用它們來處理來自同一主機的多個請求,幫助實現更高的數據吞吐量。
代理是做什么的?
Agent
管理 HTTP 客戶端的連接持久性。 它維護給定主機和端口的待處理請求隊列,為每個請求重用單個套接字連接,直到隊列為空。 之后,如果keepAlive
設置為false
,則套接字將被銷毀。 如果keepAlive
設置為true
,則套接字將放入一個池中,在那里它會被再次用於對同一主機和端口的請求。 但是,服務器可能仍會關閉空閑連接。
當客戶端或服務器關閉連接時,它會從池中刪除。 池中任何未使用的套接字都將被取消引用,以免在沒有未完成請求時保持 Node.js 進程運行。
如果使用啟用了keepAlive
的代理,那么最好在不再使用agent
時明確關閉該agent
。 否則,套接字可能會在服務器終止它們之前掛起很長時間。 未使用的套接字消耗操作系統資源。
globalAgent
http.request()
或http.get()
方法用於從 Node.js 服務器或 Node.js 客戶端應用程序向其他服務器發出 http 請求。 為了發出這些請求,默認使用http.globalAgent
。
http.globalAgent
是一個單例對象。 在 Node.js 的源代碼中, http.globalAgent
是使用帶有默認選項的new http.Agent()
創建的。
每個agent
對象都有自己的套接字數組。 因此,當您使用http.Agent
創建自定義代理時,它將具有一組與http.globalAgent
不同的套接字。 globalAgent
未使用的套接字將在超時后自動銷毀。
如上所述,如果您在同一個節點進程中啟動兩個服務器並在服務器代碼之后發出 http 請求,則請求將通過同一個globalAgent
。 服務器 1 和 2 與您的代碼中發出的http.get()
請求無關。 http.get()
將在服務器代碼之外執行。 但是,您也可以從您的服務器代碼向另一台服務器發出 http 請求,如下所示:
const server1 = http.createServer(function(req, res) {
http.get('/someurl');
res.end('The request has been made from server1');
}).listen(3000);
如果您未使用new http.Agent()
指定自定義代理,或者未在請求選項中指定{agent : false}
,則http.globalAgent
也將用於上述代碼。
agent.createConnection()
當您想避免創建自定義代理以及http.globalAgent
時,將使用函數agent.createConnection()
。 此函數直接為您提供一個用於發出 http 請求的套接字。
希望這能消除您對 HTTP 代理的所有疑慮!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.