-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http: added closeAllConnections and closeIdleConnections to http.server #42812
Conversation
Review requested:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
For API consistency I'm -0 on this. |
Isn't the |
Well, the connections list is not exposed to the developer, so they can't really do that. I agree that all the |
Actually it is bug in the implementation - Once non-idle requests have been served, they have to be evicted as well. Thanks for noticing it, I'll update this shortly. |
All servers emit the |
I see, make sense. I thought you were talking about the new data structure I recently introduced. |
Unfortunately that introduces a major overhead that makes it unfeasible in userland. @ShogunPanda or @jsumners could produce more evidence of this but we have researched this extensively. |
I'm interested because it only takes a set of references to already existing objects. I would be surprised if that turns out to be a major overhead. |
I believe this PR is a direct result of:
The primary issue that impacts performance is retaining references to the requests associated with the sockets. Ideally, this feature would let any active requests finish and then reap the remaining sockets. Currently, Node waits for all sockets to close before terminating even if there are no pending requests on those sockets. According to information in the above links, information about pending requests is not publicly available from the socket reference. So it isn't possible to determine if any requests are pending in "user land" without also keeping track of the requests. The force close implementation in Fastify ignores this and terminates all sockets regardless of whether or not any requests are currently active. This is a poor implementation, but was the only remotely performant way to get it done. |
I understand but in this case the patch would only be useful if the const http = require('http');
const sockets = new Set();
const server = http.createServer();
server.on('connection', function (socket) {
sockets.add(socket);
socket.on('close', socketOnClose);
});
function socketOnClose() {
sockets.delete(this);
}
server.close();
for (const socket of sockets) {
socket.destroy();
} |
@lpinca Yes, for the |
About the WebSocket objections, you are also right. But we assume developers know what they are doing :) The |
As a different solution to achieve this, I might leave close as it is now and add the following new methods to
The reason for 1 is to being able to solve the issue without changing existing functionality. The reason for 2 is to enable developer to do custom connections handling without having to trace them via EE. What do you think? |
Will exposing the connection lists be enough to implement this feature in userland? |
Absolutely. The other method would just become a fancy for loop. |
Then let's expose the lists. |
6c1388e
to
8b2bdd6
Compare
Done. @nodejs/http @lpinca Can you please re-review? |
doc/api/http.md
Outdated
@@ -1443,6 +1443,31 @@ This event is guaranteed to be passed an instance of the {net.Socket} class, | |||
a subclass of {stream.Duplex}, unless the user specifies a socket | |||
type other than {net.Socket}. | |||
|
|||
### `server.activeConnections()` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A request is not a connection. A request is a communication across a connection. I think server.activeConnections
is misleading. According to the subsequent docs, it is server.activeRequests
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, it's connections. I return the sockets, even though the way the sockets are categorized is given by whether there is an active/expired request being sent through it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this help with draining connections? The socket
does not expose the requests associated with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point now.
Let me clarify that, of all these methods, only allConnections
and idleConnections
are strictly needed to properly implement the forced close logic.
But I do see your point and, on a second thought, it makes sense to expose the requests rather than socket. This way the developer has all the needed informations to implement any logic they might want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point is that requests are typically short lived. Whereas connections can be open for literal wall clock minutes. What Node.js currently supports is:
.close
stops listening for new connections but waits for current connections to end before the process can exit. This scenario allows new requests on existing connections until they timeout.
There are two other scenarios that can/should be supported:
- Terminate all connections regardless of pending/active requests such that the process can terminate. This is the scenario Fastify is currently implementing.
- Stop listening for new connections and stop accepting new requests while allowing current requests to finish and subsequently terminating the associated connections.
We have seen other communities provide scenario 1, so maybe 2 isn't feasible. I don't know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2 is hard as it needs a check every time a request is finished. Which will impact performance. So eventually (which is the intention of this PR) we go with 1 (as suggested in my last comment).
doc/api/http.md
Outdated
@@ -1453,6 +1478,18 @@ added: v0.1.90 | |||
|
|||
Stops the server from accepting new connections. See [`net.Server.close()`][]. | |||
|
|||
### `server.expiredConnections()` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not clear what this provides. If a request is expired, that means Node is no longer tracking it, correct? Similarly, if a connection has expired it should have also been removed by Node, yes? So what utility does this method provide?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are 90% right. The thing is that the Node evicts expired connection every http.Server.connectionsCheckingInterval
milliseconds (default is 30s), so it can definitely happen that connections are expired but not evicted yet. Hence this method to eventually allow the user to do other things (like log these connections before evictions or similar).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constructing potentially large lists of resources generally feels like an anti-pattern in Node.js, and unless the application code is entirely synchronous, it is prone to race conditions.
Notable changes: * Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (Livia Medeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 PR-URL: TBD
Notable changes: * Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (Livia Medeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 PR-URL: TBD
Notable changes: * Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (Livia Medeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 PR-URL: #43036
Notable changes: * Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (Livia Medeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 PR-URL: #43036
Notable changes: * This release updates OpenSSL to 3.0.3. This update can be treated as a security release as the issues addressed in OpenSSL 3.0.3 slightly affect Node.js 18. See https://nodejs.org/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022/ for more information on how the May 2022 OpenSSL releases affect other Node.js release lines. * *Revert*_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: update archs files for quictls/openssl-3.0.3+quic (RafaelGSS) #43022 * deps: update undici to 5.2.0 (Node.js GitHub Bot) #43059 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 * deps: upgrade openssl sources to quictls/openssl-3.0.3 (RafaelGSS) #43022 * doc: add LiviaMedeiros to collaborators (LiviaMedeiros) #43039 * doc: add release key for Juan Arboleda (Juan José) #42961 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Paolo Insogna) #42812 * perf_hooks: add PerformanceResourceTiming (RafaelGSS) #42725 PR-URL: #43036
OpenSSL This update can be treated as a security release as the issues addressed in OpenSSL 3.0.3 slightly affect Node.js 18. See https://nodejs.org/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022/ for more information on how the May 2022 OpenSSL releases affect other Node.js release lines. * deps: update archs files for quictls/openssl-3.0.3+quic (RafaelGSS) #43022 * deps: upgrade openssl sources to quictls/openssl-3.0.3 (RafaelGSS) #43022 Other Notable changes * *Revert*_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: update undici to 5.2.0 (Node.js GitHub Bot) #43059 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 * doc: add LiviaMedeiros to collaborators (LiviaMedeiros) #43039 * doc: add release key for Juan Arboleda (Juan José) #42961 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Paolo Insogna) #42812 * perf_hooks: add PerformanceResourceTiming (RafaelGSS) #42725 PR-URL: #43036
OpenSSL This update can be treated as a security release as the issues addressed in OpenSSL 3.0.3 slightly affect Node.js 18. See https://nodejs.org/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022/ for more information on how the May 2022 OpenSSL releases affect other Node.js release lines. * deps: update archs files for quictls/openssl-3.0.3+quic (RafaelGSS) #43022 * deps: upgrade openssl sources to quictls/openssl-3.0.3 (RafaelGSS) #43022 Other Notable Changes * *Revert*_ "deps: add template for generated headers" (Daniel Bevenius) #42978 * deps: update undici to 5.2.0 (Node.js GitHub Bot) #43059 * deps: upgrade npm to 8.9.0 (npm team) #42968 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 * doc: add LiviaMedeiros to collaborators (LiviaMedeiros) #43039 * doc: add release key for Juan Arboleda (Juan José) #42961 * (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 * (SEMVER-MINOR) http: added connection closing methods (Paolo Insogna) #42812 * perf_hooks: add PerformanceResourceTiming (RafaelGSS) #42725 PR-URL: #43036
Notable changes: OpenSSL 3.0.3 This update can be treated as a security release as the issues addressed in OpenSSL 3.0.3 slightly affect Node.js 18. See https://nodejs.org/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022/ for more information on how the May 2022 OpenSSL releases affect other Node.js release lines. - deps: update archs files for quictls/openssl-3.0.3+quic (RafaelGSS) #43022 - deps: upgrade openssl sources to quictls/openssl-3.0.3 (RafaelGSS) #43022 Other notable changes: - _Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 - deps: update undici to 5.2.0 (Node.js GitHub Bot) #43059 - deps: upgrade npm to 8.9.0 (npm team) #42968 - (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 - (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 - doc: add LiviaMedeiros to collaborators (LiviaMedeiros) #43039 - doc: add release key for Juan Arboleda (Juan José) #42961 - (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 - (SEMVER-MINOR) http: added connection closing methods (Paolo Insogna) #42812 - (SEMVER-MINOR) perf_hooks: add PerformanceResourceTiming (RafaelGSS) #42725 PR-URL: #43036
Notable changes: OpenSSL 3.0.3 This update can be treated as a security release as the issues addressed in OpenSSL 3.0.3 slightly affect Node.js 18. See https://nodejs.org/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022/ for more information on how the May 2022 OpenSSL releases affect other Node.js release lines. - deps: update archs files for quictls/openssl-3.0.3+quic (RafaelGSS) #43022 - deps: upgrade openssl sources to quictls/openssl-3.0.3 (RafaelGSS) #43022 Other notable changes: - _Revert_ "deps: add template for generated headers" (Daniel Bevenius) #42978 - deps: update undici to 5.2.0 (Node.js GitHub Bot) #43059 - deps: upgrade npm to 8.9.0 (npm team) #42968 - (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 - (SEMVER-MINOR) http: added connection closing methods (Shogun) #42812 - doc: add LiviaMedeiros to collaborators (LiviaMedeiros) #43039 - doc: add release key for Juan Arboleda (Juan José) #42961 - (SEMVER-MINOR) fs: add `read(buffer[, options])` versions (LiviaMedeiros) #42768 - (SEMVER-MINOR) http: added connection closing methods (Paolo Insogna) #42812 - (SEMVER-MINOR) perf_hooks: add PerformanceResourceTiming (RafaelGSS) #42725 PR-URL: #43036
Some parts of this rely on top of #41263, I did not find a way to rapidly backport this |
@juanarbol Unfortunately I don't think it's possible without backporting both PR. The problem is that #41263 is semver-major |
That's a shame 💔 |
Sorry for posting on an old issue, but was #42812 (comment) ever done? Running |
@SimenB No, it was not done yet. I'll fix it soon. |
This PR introduces two new methods on
http.Server
andhttps.Server
:closeAllConnections()
: Closes all sockets connected to the server.closeIdleConnections()
: Closes all sockets connected to the server which are not actively sending a request or waiting for a response.Fixes #41578.