我们有一个node.js服务器,它实现了一个REST API作为中央服务器的代理,该服务器具有略微不同且不幸的非对称REST API。
我们的客户端在各种浏览器中运行,要求节点服务器从中央服务器获取任务。节点服务器从中央任务ID获取所有任务ID的列表,并将它们返回给客户端。然后,客户端通过代理为每个id发出两个REST API调用。
据我所知,这些东西都是异步完成的。在控制台日志中,当我启动客户端时它看起来像这样:
Requested GET URL under /api/v1/tasks/*: /api/v1/tasks/
从中央服务器获取列表需要几秒钟。一旦得到响应,服务器就会很快地解决这个问题:
Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/438
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/438
Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/439
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/439
Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/441
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/441
然后,每当这对请求从中央服务器获得结果时,另外两行很快被禁止。
所以我们的node.js服务器似乎只愿意一次发出六个请求。
答案 0 :(得分:155)
Node本身没有强加TCP连接限制。 (重点是它是高度并发的,可以处理数千个同时连接。)您的操作系统可能限制TCP连接。
您更有可能遇到后端服务器的某种限制,或者您正在达到内置HTTP库的连接限制,但如果没有关于该服务器或Node实现的更多详细信息,很难说。 / p>
Node的内置HTTP library(显然任何构建在它上面的库,大多数都是)维护一个连接池(通过Agent
类),以便它可以利用HTTP keep-alives 。当您向同一服务器运行许多请求时,这有助于提高性能:而不是打开TCP连接,发出HTTP请求,获取响应,关闭TCP连接,然后重复;可以在重用的TCP连接上发出新请求。
在节点0.10及更早版本中,默认情况下,HTTP代理仅打开5个同时连接到单个主机的连接。您可以轻松更改此内容:(假设您将require
HTTP模块设为http
)
http.globalAgent.maxSockets = 20; // or whatever
节点0.12将默认maxSockets
设置为Infinity
。
您可能希望保留某种连接限制。您不希望在一秒钟内完成数百个HTTP请求后完全压倒您的后端服务器 - 性能很可能比您让代理的连接池执行其操作更糟糕,限制请求以便不会使服务器过载。您最好的选择是运行一些实验,以了解您的情况下最佳并发请求数。
但是,如果您确实不想要连接池,则可以完全绕过池 - 在请求选项中将agent
发送到false
:
http.get({host:'localhost', port:80, path:'/', agent:false}, callback);
在这种情况下,并发HTTP请求绝对没有限制。
答案 1 :(得分:12)
这是浏览器中并发连接数的限制:
How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?
我赞成其他答案,因为他们帮助我诊断问题。线索是节点的套接字限制是5,我一次得到6。 6是Chrome中的限制,这是我用来测试服务器的。
答案 2 :(得分:6)
您是如何从中央服务器获取数据的?使用http
模块发出HTTP请求时,“节点不限制连接”并不完全准确。以这种方式发出的客户端请求使用http.globalAgent
的{{1}}实例,每个http.Agent
都有一个名为http.Agent
的设置,用于确定代理可以向任何给定的套接字打开多少个套接字主办;默认为5。
因此,如果您使用maxSockets
或http.request
(或依赖这些方法的库)从中央服务器获取数据,您可以尝试更改{{1}的值(或在您正在使用的http.get
的任何实例上修改该设置。)
请参阅:
答案 3 :(得分:2)
我在服务器上看到了同样的问题。它只处理4个请求。 正如已经从0.12 maxsockets默认为无穷大所解释的那样。这很容易超过服务器。
将请求限制为10http.globalAgent.maxSockets = 20;
解决了我的问题。
答案 4 :(得分:1)
您确定它只是将结果返回给客户端吗? Node在一个线程中处理所有内容。因此,如果你做一些花哨的响应解析或其他任何不产生的东西,那么它会阻止你的所有请求。
答案 5 :(得分:0)
Node js可以处理数千个传入请求-是的!
但是当涉及到无用的请求时,每个请求都必须处理dns查找和dns查找,磁盘读取等操作由用C ++编程的libuv处理。每个节点进程的线程默认值为4个线程。
如果所有4x线程都忙于https请求(dns查找),则其他请求将排队。这就是为什么您的代码多么出色的原因:您有时每秒完成6个或更少的并发传出请求。
了解有关dns缓存的信息,以减少dns查找的数量并增加libuv大小。如果您使用PM2来管理您的节点进程,那么它们在环境变量以及如何注入它们方面确实有完善的文档。您正在寻找的是环境变量UV_THREADPOOL_SIZE = 4
您可以将值设置为1或最大限制1024之间的任意值。但是请记住,所有事件循环中的libuv限制为1024。