[英]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.