Skip to content

HTTP client connection pooling and keep-alive behavior is confusing #10774

@lance

Description

@lance
  • Version: v7.4.0
  • Platform: Darwin Lances-MacBook-Pro.local 16.3.0 Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64 x86_64
  • Subsystem: http, net

Due to what I thought would be a simple documentation PR, I have recently started investigating how http.Agent works for both connection pooling and HTTP keep-alive behavior. I am much confused. I would like to know if my understanding of the existing code is correct, and if so, is this the intended behavior.

The following text is a copy/paste of one of my comments from that documentation pull request.

I have been reading the code all morning, and the keep alive logic is mind boggling, shared between _http_outgoing.js, _http_agent.js, _http_client.js, and net.js. If I'm reading it correctly, as far as clients go, by default, we're not implementing HTTP/1.1 persistence.

The HTTP/1.1 spec says,

A significant difference between HTTP/1.1 and earlier versions of HTTP is that persistent connections are the default behavior of any HTTP connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server.

Both the http.globalAgent and the default constructor behave so that multiple, simultaneous requests will reuse an existing connection, but once the Agent instance has no more pending requests for a given host/port, the socket is destroyed, instead of assuming the server will maintain the connection.

But really, I wonder if this is the intended behavior. It's not necessarily broken, but seems like an odd default. That, combined with the fact that the default also does not pool sockets -- you must specify keepAlive: true to enable this -- makes it seems like the Agent doesn't do much on its own, unless expressly created/configured to do so.

To summarize. If I read it correctly, the default behavior for all HTTP client requests using an Agent (even the default http._globalAgent is to:

I would love for someone with better knowledge of the code to chime in here. My reading of the code could be wrong. But if it's correct, it sure is confusing and I find it hard to believe this is the true intent.

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpIssues or PRs related to the http subsystem.netIssues and PRs related to the net subsystem.questionIssues that look for answers.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions