简体   繁体   English

Node.js:http.Server、http.Agent、sockets、http.request 之间的关系

[英]Node.js: Relationship among http.Server, http.Agent, sockets, and http.request

Per the docs :根据文档

Node.js maintains several connections per server to make HTTP requests. Node.js 为每个服务器维护多个连接以发出 HTTP 请求。 This function allows one to transparently issue requests.此功能允许透明地发出请求。

The docs further specify that Node relies on http.globalAgent to make requests by default, but that you can use your own agent by creating a new http.Agent .文档进一步指定 Node 默认依赖http.globalAgent发出请求,但您可以通过创建新的http.Agent来使用自己的代理。 Agents are used to "pool sockets" for http requests.代理用于为 http 请求“池化套接字”。

My interpretation of all this is that each time you do a http.createServer , by default you get several sockets (presumably that is what is meant by "connections") to make http requests and these sockets are pooled / managed by http.globalAgent .我对这一切的解释是,每次执行http.createServer ,默认情况下都会获得多个套接字(大概这就是“连接”的意思)来发出 http 请求,并且这些套接字由http.globalAgent汇集/管理。

What isn't clear to me is what happens when you create your own http.Agent .我不清楚的是当您创建自己的http.Agent时会发生什么。 Does the Agent just "take over" the sockets that were previously being managed by http.globalAgent ? Agent是否只是“接管”以前由http.globalAgent管理的http.globalAgent Or do you have to create a new socket for your new Agent via agent.createConnection ?或者您是否必须通过agent.createConnection为您的新Agent创建一个新套接字?

On a related note, if I were to start up two servers in the same node process and subsequently make an http request, eg在相关说明中,如果我要在同一个节点进程中启动两个服务器并随后发出 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');

from which server would the request be made?从哪个服务器发出请求? Does http.Agent come into play here? http.Agent在这里发挥作用吗?

Even I was confused with the same, but recently I found the answers.甚至我也对此感到困惑,但最近我找到了答案。

Agents and globalAgent代理和全局代理

Agents are the source used by the Node to make requests to a new server.代理是节点用来向新服务器发出请求的源。 Here you can find that the Agent makes a request call. 在这里您可以发现 Agent 发出请求调用。 The Agent needs to have the host, port and some other custom headers (KeepAlive etc) to send a request.代理需要有主机、端口和一些其他自定义标头(KeepAlive 等)来发送请求。 If no agent is specified then Node uses globalAgent by default.如果未指定代理,则 Node 默认使用 globalAgent。 From here we can analyze that most of the headers are set by default. 从这里我们可以分析,大多数标题都是默认设置的。 Both of these are helpful in making a request, so if you have a service running at 127.0.0.1:8080 you can make a request using these.这两者都有助于发出请求,因此如果您的服务在 127.0.0.1:8080 上运行,则可以使用它们发出请求。

Sockets插座

As you mentioned, Sockets are the connections and using these connections the requests are made to the given server.正如您所提到的,套接字是连接,使用这些连接向给定服务器发出请求。 These sockets are managed by the OS(say Linux), it creates a new socket handler for each socket.这些套接字由操作系统(比如 Linux)管理,它为每个套接字创建一个新的套接字处理程序。 The list of sockets for a particular domain is however maintained in the Agent/globalAgent.然而,特定域的套接字列表在 Agent/globalAgent 中维护。 We can set the maxSockets , maxFreeSockets etc. These help us in keeping a check on the usage of OS resources.我们可以设置maxSocketsmaxFreeSockets等。这些有助于我们检查操作系统资源的使用情况。

When a new agent is created, it shall manage the connections of the requests that are made from it.当一个新的代理被创建时,它应该管理从它发出的请求的连接。 agent.createConnection creates a TCP socket. agent.createConnection 创建一个 TCP 套接字。 Here it is mentioned that it returns net.socket, so you can listen on this socket for any streams using events. 这里提到它返回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);

In this code, there are 2 servers created and they are listening at 3000 and 5000. These shall serve the requests made by clients.在此代码中,创建了 2 个服务器,它们分别在 3000 和 5000 处侦听。它们应为客户端发出的请求提供服务。 These have nothing to do with the request that you make.这些与您提出的请求无关。 You can make a get request without creating a server.您可以在不创建服务器的情况下发出 get 请求。 All the requests you make are handled by the Agent, so the get method in the line您发出的所有请求都由代理处理,因此该行中的 get 方法

http.get('/someurl');

actually uses the HttpAgent.实际上使用了HttpAgent。

Further Reads:进一步阅读:

  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 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://www.hacksparrow.com/tcp-socket-programming-in-node-js.html

HTTP Agent HTTP Agent

Why do we need the Agent ?为什么我们需要Agent

The process of establishing a connection from one host to another involves multiple packet exchanges between two endpoints, this can be quite time consuming, especially for multiple small http requests.建立从一台主机到另一台主机的连接的过程涉及两个端点之间的多个数据包交换,这可能非常耗时,尤其是对于多个小的 http 请求。 The Agent helps achieve a much higher data throughput by keeping the connections open and by reusing them to handle multiple requests from the same host. Agent通过保持连接打开并重用它们来处理来自同一主机的多个请求,帮助实现更高的数据吞吐量。

What does the Agent do?代理是做什么的?

The Agent manages connection persistence for HTTP clients. Agent管理 HTTP 客户端的连接持久性。 It maintains a queue of pending requests for a given host and port, reusing a single socket connection for each until the queue is empty.它维护给定主机和端口的待处理请求队列,为每个请求重用单个套接字连接,直到队列为空。 After that, the socket is destroyed, if the keepAlive is set to false .之后,如果keepAlive设置为false ,则套接字将被销毁。 If the keepAlive is set to true , the socket is put into a pool where it is kept to be used again for requests to the same host and port.如果keepAlive设置为true ,则套接字将放入一个池中,在那里它会被再次用于对同一主机和端口的请求。 However, servers may still close idle connections.但是,服务器可能仍会关闭空闲连接。


Socket Management套接字管理

When a connection is closed by the client or the server, it is removed from the pool.当客户端或服务器关闭连接时,它会从池中删除。 Any unused sockets in the pool will be unrefed so as not to keep the Node.js process running when there are no outstanding requests.池中任何未使用的套接字都将被取消引用,以免在没有未完成请求时保持 Node.js 进程运行。

If using an agent with keepAlive enabled, then it is best to explicitly shut down the agent when it will no longer be used.如果使用启用了keepAlive的代理,那么最好在不再使用agent时明确关闭该agent Otherwise, sockets may hang open for quite a long time before the server terminates them.否则,套接字可能会在服务器终止它们之前挂起很长时间。 Unused sockets consume OS resources.未使用的套接字消耗操作系统资源。


HTTP globalAgent HTTP globalAgent

The http.request() or http.get() method is used to make http requests to other servers from your Node.js server or your Node.js client app. http.request()http.get()方法用于从 Node.js 服务器或 Node.js 客户端应用程序向其他服务器发出 http 请求。 For making these requests, the http.globalAgent is used by default.为了发出这些请求,默认使用http.globalAgent

http.globalAgent is a singleton object. http.globalAgent是一个单例对象。 In the source code of Node.js, the http.globalAgent is created using new http.Agent() with default options.在 Node.js 的源代码中, http.globalAgent是使用带有默认选项的new http.Agent()创建的。

Each agent object has its own array of sockets.每个agent对象都有自己的套接字数组。 So, when you create a custom agent using http.Agent , it will have a different set of sockets from http.globalAgent .因此,当您使用http.Agent创建自定义代理时,它将具有一组与http.globalAgent不同的套接字。 The unused sockets of the globalAgent will be destroyed automatically after the timeout. globalAgent未使用的套接字将在超时后自动销毁。


Multiple Servers in a Process一个进程中的多个服务器

As specified in question, if you start the two servers in the same node process and make the http request after the server code, the request will go through the same globalAgent .如上所述,如果您在同一个节点进程中启动两个服务器并在服务器代码之后发出 http 请求,则请求将通过同一个globalAgent The server 1 and 2 are irrelevant to the http.get() request made in your code.服务器 1 和 2 与您的代码中发出的http.get()请求无关。 The http.get() will be executed outside of the server code. http.get()将在服务器代码之外执行。 However, you can also make an http request to another server from your server code as shown below:但是,您也可以从您的服务器代码向另一台服务器发出 http 请求,如下所示:

const server1 = http.createServer(function(req, res) {
  http.get('/someurl');
  res.end('The request has been made from server1');
}).listen(3000);

If you don't specify your custom agent using the new http.Agent() or if you don't specify {agent : false} in your request options, the http.globalAgent will be used for the code above too.如果您未使用new http.Agent()指定自定义代理,或者未在请求选项中指定{agent : false} ,则http.globalAgent也将用于上述代码。


agent.createConnection()

The function agent.createConnection() is used when you want to avoid creating a custom agent as well as http.globalAgent .当您想避免创建自定义代理以及http.globalAgent时,将使用函数agent.createConnection() This function directly gives you a socket for making your http request.此函数直接为您提供一个用于发出 http 请求的套接字。


Hope this clears all your doubts about the HTTP Agent!希望这能消除您对 HTTP 代理的所有疑虑!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM