TL; DR-大量の同時リクエストで高スループットを可能にするglobalAgentを構成する際のベストプラクティスはありますか?
これが私たちの問題です:
私の知る限り、Nodeの接続プールはhttpモジュールによって管理されています。このモジュールは、Nodeプロセスに対してグローバルなglobalAgentオブジェクトにリクエストをキューに入れます。任意の時点でglobalAgentキューからプルされる要求の数は、開いているソケット接続の数によって決まります。これは、globalAgentのmaxSocketsプロパティ(デフォルトは5)によって決まります。
「キープアライブ」接続を使用する場合、リクエストが解決されるとすぐに、リクエストを処理した接続が使用可能になり、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