簡體   English   中英

Node.js:http.Server、http.Agent、sockets、http.request 之間的關系

[英]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 中維護。 我們可以設置maxSocketsmaxFreeSockets等。這些有助於我們檢查操作系統資源的使用情況。

當一個新的代理被創建時,它應該管理從它發出的請求的連接。 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。

進一步閱讀:

  1. https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Fwyicwx.github.io%2F2014%2F03%2F12%2F%25E8% 25B0%2588%25E8%25B0%2588nodejs%25E4%25B8%25ADhttpagent%2F&edit-text=&act=url
  2. http://www.hacksparrow.com/tcp-socket-programming-in-node-js.html

HTTP Agent

為什么我們需要Agent

建立從一台主機到另一台主機的連接的過程涉及兩個端點之間的多個數據包交換,這可能非常耗時,尤其是對於多個小的 http 請求。 Agent通過保持連接打開並重用它們來處理來自同一主機的多個請求,幫助實現更高的數據吞吐量。

代理是做什么的?

Agent管理 HTTP 客戶端的連接持久性。 它維護給定主機和端口的待處理請求隊列,為每個請求重用單個套接字連接,直到隊列為空。 之后,如果keepAlive設置為false ,則套接字將被銷毀。 如果keepAlive設置為true ,則套接字將放入一個池中,在那里它會被再次用於對同一主機和端口的請求。 但是,服務器可能仍會關閉空閑連接。


套接字管理

當客戶端或服務器關閉連接時,它會從池中刪除。 池中任何未使用的套接字都將被取消引用,以免在沒有未完成請求時保持 Node.js 進程運行。

如果使用啟用了keepAlive的代理,那么最好在不再使用agent時明確關閉該agent 否則,套接字可能會在服務器終止它們之前掛起很長時間。 未使用的套接字消耗操作系統資源。


HTTP 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM