Node.js:http.Server,http.Agent,套接字和http.request之间的关系

时间:2016-05-26 21:29:48

标签: javascript node.js http

根据docs

  

Node.js为每个服务器维护多个连接以发出HTTP请求。此功能允许用户透明地发出请求。

文档进一步指定Node默认依赖http.globalAgent发出请求,但您可以通过创建新的http.Agent来使用自己的代理。代理用于为http请求“池套接字”。

我对所有这些的解释是,每次执行http.createServer时,默认情况下会得到几个套接字(可能是“连接”的含义)来发出http请求并且这些套接字是汇集/管理的http.globalAgent

我不清楚当您创建自己的http.Agent时会发生什么。 Agent只是“接管”以前由http.globalAgent管理的套接字吗?或者您是否必须通过Agent为新的agent.createConnection创建一个新套接字?

在相关的说明中,如果我要在同一节点进程中启动两个服务器并随后发出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会在这里发挥作用吗?

2 个答案:

答案 0 :(得分:2)

HTTP Agent

我们为什么需要Agent

从一台主机到另一台主机建立连接的过程涉及两个端点之间的多次数据包交换,这可能会非常耗时,尤其是对于多个小型http请求。 Agent通过保持连接打开并重用它们来处理来自同一主机的多个请求,可以帮助实现更高的数据吞吐量。

代理做什么?

Agent管理HTTP客户端的连接持久性。它为给定的主机和端口维护一个未决请求队列,为每个主机和端口重用单个套接字连接,直到队列为空。此后,如果将keepAlive设置为false,则套接字将被销毁。如果将keepAlive设置为true,则将套接字放入一个池中,并在该池中保留该套接字以再次用于向同一主机和端口的请求。但是,服务器仍可能关闭空闲连接。


套接字管理

当客户端或服务器关闭连接时,该连接将从池中删除。池中任何未使用的套接字都将被取消引用,以免在没有未完成的请求时不让Node.js进程运行。

如果使用启用了keepAlive的代理,则最好在不再使用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()

当您要避免创建自定义代理以及agent.createConnection()时,可以使用函数http.globalAgent。该功能直接为您提供了一个用于发出http请求的套接字。


希望这消除了您对HTTP代理的所有疑问!

答案 1 :(得分:0)

即使我对此感到困惑,但最近我找到了答案。

  

代理商和globalAgent

代理是节点用来向新服务器发出请求的来源。 Here,您会发现代理程序发出了请求呼叫。代理需要具有主机,端口和一些其他自定义标头(KeepAlive等)才能发送请求。 如果未指定代理,则默认情况下,Node使用globalAgent。 From here我们可以分析大多数标题是默认设置的。两者都对发出请求很有帮助,因此,如果您有一个运行在127.0.0.1:8080的服务,则可以使用它们进行请求。

  

套接字

正如您提到的,套接字是连接,使用这些连接可以将请求发送到给定的服务器。这些套接字由OS(例如Linux)管理,它为每个套接字创建一个新的套接字处理程序。但是,特定域的套接字列表在代理/ globalAgent中维护。我们可以设置maxSocketsmaxFreeSockets等。这些有助于我们检查操作系统资源的使用情况。

创建新代理后,它将管理从其发出的请求的连接。 agent.createConnection创建一个TCP套接字。 Here提到它返回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方法

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