FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

http: Change free sockets behavior to LIFO from FIFO. by rustyconover · Pull Request #31526 · nodejs/node · GitHub

/ node Public

http: Change free sockets behavior to LIFO from FIFO. - #31526

Closed
rustyconover wants to merge 2 commits into
nodejs:masterfrom
rustyconover:fix-https-agent-oldest-sockets
Closed

http: Change free sockets behavior to LIFO from FIFO.#31526
rustyconover wants to merge 2 commits into
nodejs:masterfrom
rustyconover:fix-https-agent-oldest-sockets

Conversation

Copy link
Copy Markdown
Contributor

Sockets are added to the free list with .push() but they were
being removed with .shift(). This meant the sockets where being
removed in FIFO order, but this changes it to LIFO. Since older
sockets may be closed based due to inactivity on the server it is
more likely that a socket that is recently used will be able to
successfully process the next request.

  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows

nodejs-github-bot added the http Issues or PRs related to the http subsystem. label Jan 26, 2020

ronag commented Jan 27, 2020
edited
Loading

Copy link
Copy Markdown
Member

On the other hand sockets that have not been used in a while might unnecessarily timeout. I think LIFO is fine but we do need to remove sockets from the free list when they timeout (which we currently don't).

I'm unsure whether LIFO or FIFO is better here...

Also, this might be a good idea to apply when the free list is full, i.e. instead of throwing away the most recent socket (as we currently do), we should throw away the least recently used.

Copy link
Copy Markdown
Contributor Author

Why would we want to remove then until we actually try them? That's the current behavior.

You have a good idea on the second part about what should be thrown away, updated commit pending.

ronag commented Jan 27, 2020

Copy link
Copy Markdown
Member

Why would we want to remove then until we actually try them? That's the current behavior.

Because they have timed out. I don't think that's the current behavior?

Copy link
Copy Markdown
Contributor Author

Are there event handlers still reading from the socket once they are placed in the agent pool? I don't believe so. If there aren't any handlers waiting to read how will the code know the socket has timed out?

ronag commented Jan 27, 2020

Copy link
Copy Markdown
Member

If there aren't any handlers waiting to read how will the code know the socket has timed out?

By adding a handler. See, #23752.

rustyconover requested a review from ronag January 27, 2020 16:28
Comment thread lib/_http_agent.js Outdated
rustyconover requested a review from ronag January 27, 2020 18:06
Comment thread lib/_http_agent.js
this.maxFreeSockets > 0 &&
count <= this.maxSockets) {
if (freeLen >= this.maxFreeSockets) {
const oldest = this.freeSockets[name].shift();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit, freeSockets.shift()

Comment thread lib/_http_agent.js
if (freeLen >= this.maxFreeSockets) {
const oldest = this.freeSockets[name].shift();
oldest.destroy();
} else {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit, else if (!freeSockets)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm not quite following, could you explain a bit more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

the block inside of the else is for the case when !freeSockets, could be simplified

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

it's a nit, no biggie

ronag commented Jan 27, 2020

Copy link
Copy Markdown
Member

Would be nice if you could make a test for this.

jasnell added the semver-major PRs that contain breaking changes and should be released in the next major version. label Jan 27, 2020

jasnell commented Jan 27, 2020

Copy link
Copy Markdown
Member

Defensively marking this semver-major for now. It's possible this wouldn't break anyone but we need to verify.

jasnell commented Jan 27, 2020

Copy link
Copy Markdown
Member

Ping @nodejs/http

Trott commented Jan 28, 2020

Copy link
Copy Markdown
Member

A benchmark would be good. We might already have a relevant benchmark. I'm not sure.

Would be nice if you could make a test for this.

At least in theory, isn't this an implementation detail the user need not worry about? (But I wouldn't oppose a test either. Just not sure if it's necessary.)

ronag commented Jan 28, 2020

Copy link
Copy Markdown
Member

At least in theory, isn't this an implementation detail the user need not worry about?

Agreed. Nice to have.

Sockets are added to the free list with .push() but they were
being removed with .shift().  This meant the sockets where being
removed in FIFO order, but this changes it to LIFO.  Since older
sockets may be closed based due to inactivity on the server it is
more likely that a socket that is recently used will be able to
successfully process the next request.

Rather than destroying the last used socket destroy
the oldest socket in the free list in push() on the
last recently used socket.
rustyconover force-pushed the fix-https-agent-oldest-sockets branch from 4ef4a2d to 5af8b39 Compare February 17, 2020 17:49

Copy link
Copy Markdown
Contributor Author

@ronag @Trott could you please mark this PR as author ready?

Trott commented Feb 27, 2020

Copy link
Copy Markdown
Member

@ronag @Trott could you please mark this PR as author ready?

Although there's some ambiguity around the author ready label, I would say this is not yet author ready because it is semver-major and therefore requires two approvals from the TSC.

/ping @nodejs/tsc Please review! (@jasnell described marking this as semver-major as being done "defensively" so it might not be semver-major after all. Opinions one way or the other are welcome.)

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I would like to have a test for this behavior.

Copy link
Copy Markdown
Member

Very good work. This is one of the main changes I did in https://github.com/mcollina/undici to improve the handling of keep-alive connections.

ronag commented Feb 27, 2020

Copy link
Copy Markdown
Member

There is a related issue to this that we might want to consider before landing this.

We have a problem with sockets in the freelist that timeout are not removed from the list. This change might make that worse, since the least recently used socket is less likely to be used and thus timeout, then when it is actually used the request using it would fail.

Copy link
Copy Markdown
Contributor Author

@ronag Does this mean that the request isn't retried on another connection automatically or is the request simply failed with a connection reset error?

Copy link
Copy Markdown
Contributor Author

@ronag is there a test case that stresses this condition?

ronag commented Feb 28, 2020
edited
Loading

Copy link
Copy Markdown
Member

@ronag Does this mean that the request isn't retried on another connection automatically or is the request simply failed with a connection reset error?

If the user doesn't abort the request in a 'timeout' event handler (this is optional at the moment), the socket might be incorrectly re-used and the corresponding request would potentially fail, probably with ECONNRESET.

@ronag is there a test case that stresses this condition?

Nope, would be nice to have a tests for it.

ronag commented Feb 28, 2020

Copy link
Copy Markdown
Member

Just to clarify, I believe my concern is already a problem, however this PR might make it worse.

ronag mentioned this pull request Feb 28, 2020
4 tasks

ronag commented Feb 28, 2020
edited
Loading

Copy link
Copy Markdown
Member

@rustyconover: I openend a separate PR to address my concern. I think this PR is good as is once a test is added, though I would prefer to wait for #32000 to land before landing this.

Copy link
Copy Markdown
Contributor Author

@ronag I just wrote a test for the LIFO behavior of this PR. Let me know what you think.

Copy link
Copy Markdown
Contributor Author

I would like to have a test for this behavior.

@mcollina I just added a test.

Add a test that ensures the HTTP agent reuses sockets
in a LIFO fashion rather than FIFO.
rustyconover force-pushed the fix-https-agent-oldest-sockets branch from 9aad728 to b43479f Compare March 1, 2020 04:31
rustyconover requested a review from mcollina March 1, 2020 04:32

Copy link
Copy Markdown
Contributor Author

@mcollina I believe I've addressed your suggestions in the updated commits. Please let me know what you think. Thank you! 🙏

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

ronag commented Mar 11, 2020

Copy link
Copy Markdown
Member

@rustyconover this has conflicts

Copy link
Copy Markdown
Member

Implemented in #33278

mcollina closed this May 20, 2020

Copy link
Copy Markdown
Contributor Author

Great! 👍

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

http Issues or PRs related to the http subsystem. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants


Back | FazBrowse Home | New Git URL