TL;DR - 配置 globalAgent 时是否有任何最佳实践,允许高吞吐量和大量并发请求?
这是我们的问题:
据我所知,Node 中的连接池由 http 模块管理,该模块在 globalAgent 对象中对请求进行排队,该对象对 Node 进程是全局的。在任何给定时间从 globalAgent 队列中拉出的请求数由打开的套接字连接数决定,该连接数由 globalAgent 的 maxSockets 属性决定(默认为 5)。
当使用“keep-alive”连接时,我希望一旦请求得到解决,处理请求的连接将可用并且可以处理 globalAgent 队列中的下一个请求。
但是,似乎在处理任何其他排队请求之前,每个连接都已解决,直到最大数量。
在观察组件之间的网络流量时,我们看到如果 maxSockets 为 10,则 10 个请求解析成功。然后有一个暂停 3-5 秒的暂停(大概是在建立新的 tcp 连接时),然后再解决 10 个请求,然后是另一个暂停,等等。
这似乎是错误的。Node 应该擅长处理大量并发请求。因此,即使有 1000 个可用的套接字连接,如果在 1-999 解决之前无法处理请求 1000,那么您就会遇到瓶颈。但是我无法弄清楚我们做错了什么。
更新
下面是我们如何发出请求的示例——尽管值得注意的是,每当节点进程发出 http 请求时都会发生这种行为,包括当该请求由广泛使用的第三方库发起时。我不认为它特定于我们的实施。尽管如此...
class Client
constructor: (@endpoint, @options = {}) ->
@endpoint = @_cleanEndpoint(@endpoint)
throw new Error("Endpoint required") unless @endpoint && @endpoint.length > 0
_.defaults @options,
maxCacheItems: 1000
maxTokenCache: 60 * 10
clientId : null
bearerToken: null # If present will be added to the request header
headers: {}
@cache = {}
@cards = new CardMethods @
@lifeStreams = new LifeStreamMethods @
@actions = new ActionsMethods @
_cleanEndpoint: (endpoint) =>
return null unless endpoint
endpoint.replace /\/+$/, ""
_handleResult: (res, bodyBeforeJson, callback) =>
return callback new Error("Forbidden") if res.statusCode is 401 or res.statusCode is 403
body = null
if bodyBeforeJson and bodyBeforeJson.length > 0
try
body = JSON.parse(bodyBeforeJson)
catch e
return callback( new Error("Invalid Body Content"), bodyBeforeJson, res.statusCode)
return callback(new Error(if body then body.message else "Request failed.")) unless res.statusCode >= 200 && res.statusCode < 300
callback null, body, res.statusCode
_reqWithData: (method, path, params, data, headers = {}, actor, callback) =>
headers['Content-Type'] = 'application/json' if data
headers['Accept'] = 'application/json'
headers['authorization'] = "Bearer #{@options.bearerToken}" if @options.bearerToken
headers['X-ClientId'] = @options.clientId if @options.clientId
# Use method override (AWS ELB problems) unless told not to do so
if (not config.get('clients:useRealHTTPMethods')) and method not in ['POST', 'PUT']
headers['x-http-method-override'] = method
method = 'POST'
_.extend headers, @options.headers
uri = "#{@endpoint}#{path}"
#console.log "making #{method} request to #{uri} with headers", headers
request
uri: uri
headers: headers
body: if data then JSON.stringify data else null
method: method
timeout: 30*60*1000
, (err, res, body) =>
if err
err.status = if res && res.statusCode then res.statusCode else 503
return callback(err)
@_handleResult res, body, callback