节点请求队列已备份

时间:2012-12-14 22:39:57

标签: node.js networking httprequest

TL; DR - 在配置允许高吞吐量和大量并发请求的globalAgent时是否有最佳实践?

以下是我们的问题:

据我所知,Node中的连接池由http模块管理,http模块在globalAgent对象中对请求进行排队,该对象对Node进程是全局的。在任何给定时间从globalAgent队列中提取的请求数由打开的套接字连接数决定,该连接数由globalAgent的maxSockets属性决定(默认为5)。

当使用“keep-alive”连接时,我希望一旦请求得到解决,处理请求的连接就可用,并且可以处理globalAgent队列中的下一个请求。

但是,在处理任何其他排队请求之前,似乎解决了最大数量的每个连接。

当观察组件之间的网络流量时,我们看到如果maxSockets为10,则10个请求成功解析。然后暂停3-5秒暂停(可能是在建立新的tcp连接时),然后再解决10个请求,然后再暂停等等。

这似乎不对。节点应该在处理大量并发请求方面表现出色。因此,即使有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

1 个答案:

答案 0 :(得分:1)

老实说,coffeescript不是我的强项,所以不能真正评论代码。

但是,我可以给你一些想法:在我们正在开展的工作中,我们使用nano连接到cloudant,我们从微型AWS实例中看到多达200个请求/ s进入cloudant。所以你是对的,节点应该达到它。

如果您还没有,请尝试使用请求https://github.com/mikeal/request。 (我不认为这会有所作为,但值得一试,因为这是纳米使用的。)

这些是我要研究的领域:

  1. 服务器不能很好地处理多个请求并限制它。您是否针对您的服务器运行了任何性能测试?如果由于某种原因它无法处理负载或者您的请求在操作系统中被限制,那么您的客户端做什么并不重要。

  2. 您的客户端代码在某处具有长时间运行的功能,可防止节点处理您从服务器返回的任何响应。也许一个特定的响应导致响应回调花费太长时间。

  3. 端点是否都是不同的服务器/主机?