Skip to content
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

Limit requests per connection #40082

Closed
wants to merge 9 commits into from

Conversation

fatal10110
Copy link
Contributor

@fatal10110 fatal10110 commented Sep 11, 2021

Trying to close #40071

Still missing tests and docs

@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Sep 11, 2021
@fatal10110 fatal10110 force-pushed the max_request_per_socket branch from 2b5d67f to 661251d Compare September 11, 2021 12:23
@@ -486,6 +487,7 @@ function connectionListenerInternal(server, socket) {
// need to pause TCP socket/HTTP parser, and wait until the data will be
// sent to the client.
outgoingData: 0,
requestsCount: 0,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure yet if state is per all sockets or there is a state per socket

Copy link
Member

Choose a reason for hiding this comment

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

this is for each individual socket

lib/_http_outgoing.js Outdated Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

If you start adding unit tests (even failing) it would help.

@@ -876,6 +878,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {

const res = new server[kServerResponse](req);
res._keepAliveTimeout = server.keepAliveTimeout;
res._maxRequestsPerSocket = server.maxRequestsPerSocket;
Copy link
Member

Choose a reason for hiding this comment

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

Why is this copied here?

Copy link
Contributor Author

@fatal10110 fatal10110 Sep 11, 2021

Choose a reason for hiding this comment

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

I'm passing maxRequestsPerSocket to res since I need to set the max value on "keep-alive` header on response
https://github.com/nodejs/node/pull/40082/files/64132000c63934af235ae59095faad2015b3a045#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556R463
Didn't found a way to do it better


if (server.maxRequestsPerSocket < ++state.requestsCount) {
res.writeHead(503);
res.end();
Copy link
Member

Choose a reason for hiding this comment

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

Is connection close correctly set here? I think shouldKeepAlive should be set to false.

res.end();
}

res.shouldKeepAlive = server.maxRequestsPerSocket > state.requestsCount
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
res.shouldKeepAlive = server.maxRequestsPerSocket > state.requestsCount
res.shouldKeepAlive = server.maxRequestsPerSocket >= state.requestsCount

I think this should go to false if they are the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the current code the shouldKeepAlive will be false if they are equal
the shouldKeepAlive is set to true only if requestsCount is small enough

server.maxRequestsPerSocket > state.requestsCount

@fatal10110
Copy link
Contributor Author

If you start adding unit tests (even failing) it would help.

Sure, Im on it right now, it just a bit complicated for me to understand how to run them (only my tests)

@fatal10110 fatal10110 closed this Sep 11, 2021
@fatal10110 fatal10110 reopened this Sep 11, 2021
@mcollina
Copy link
Member

mcollina commented Sep 11, 2021

./node test/parallel/test-your-new-test.js

@fatal10110 fatal10110 force-pushed the max_request_per_socket branch from 12d6866 to d64d618 Compare September 12, 2021 13:55
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

can you please add another test with a pipelined request coming in before the "last" (allowed) one completes.

@fatal10110
Copy link
Contributor Author

fatal10110 commented Sep 12, 2021

can you please add another test with a pipelined request coming in before the "last" (allowed) one completes.

I created a test sending 4 requests in a row with a timeout on the server side before response (timeout 5 sec) it is for sure received after the the last allow is completed, also see the code is reaching the 503 handler

        res.writeHead(503);
        res.end();

But it is not returned from the server (503) as a response, I see only the first 3
My guess is because the last one (the third one is "marked" as last=true because of shouldKeepAlive=false
not sure what to do now.

This is what I get as a response for 4 requests when limit is set to 3

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:17:24 GMT
Connection: keep-alive
Keep-Alive: timeout=5, max=3
Transfer-Encoding: chunked

c
Hello World!
0

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:17:24 GMT
Connection: keep-alive
Keep-Alive: timeout=5, max=3
Transfer-Encoding: chunked

c
Hello World!
0

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:17:24 GMT
Connection: close
Transfer-Encoding: chunked

c
Hello World!
0

@fatal10110
Copy link
Contributor Author

fatal10110 commented Sep 12, 2021

I used another flag instead of shouldKeepAlive and it worked, but there may be side effects if shouldKeepAlive is actually true,
but I send connection: close

results:

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:32:02 GMT
Connection: keep-alive
Keep-Alive: timeout=5, max=3
Transfer-Encoding: chunked

c
Hello World!
0

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:32:02 GMT
Connection: keep-alive
Keep-Alive: timeout=5, max=3
Transfer-Encoding: chunked

c
Hello World!
0

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Sun, 12 Sep 2021 19:32:02 GMT
Connection: close
Transfer-Encoding: chunked

c
Hello World!
0

HTTP/1.1 503 Service Unavailable
Date: Sun, 12 Sep 2021 19:31:52 GMT
Connection: close
Transfer-Encoding: chunked

0

lib/_http_outgoing.js Outdated Show resolved Hide resolved
@fatal10110 fatal10110 force-pushed the max_request_per_socket branch from f533750 to 84d4e8e Compare September 12, 2021 19:47
@fatal10110 fatal10110 marked this pull request as ready for review September 12, 2021 19:48
@fatal10110 fatal10110 requested a review from mcollina September 12, 2021 19:48
@nodejs-github-bot
Copy link
Collaborator

@mcollina
Copy link
Member

@fatal10110
Copy link
Contributor Author

not sure what is "test-asan" and why it failed on timeout

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

According to

https://datatracker.ietf.org/doc/html/draft-thomson-hybi-http-timeout-03#section-2.2.1

The "max" parameter has been used to indicate the maximum number of
requests that would be made on the connection. This parameter is
deprecated. Any limit on requests can be enforced by sending
"Connection: close" and closing the connection.

max is deprecated and should not be sent.

Adding a limit is actually fine and could help in production deployments let's just add that.

@fatal10110 fatal10110 force-pushed the max_request_per_socket branch from 2ed33eb to 4d0ca75 Compare September 14, 2021 11:16
@fatal10110
Copy link
Contributor Author

Done, thanks!

@artur-ma
Copy link

@mcollina anything else should be done? or should I close this PR ?

@nodejs-github-bot
Copy link
Collaborator

@artur-ma
Copy link

Filed again with some strange error

10:08:27   duration_ms: 21.359
10:08:27   severity: fail
10:08:27   exitcode: 1
10:08:27   stack: |-
10:08:27     /home/iojs/build/workspace/node-test-binary-arm/test/common/debugger.js:84
10:08:27               reject(new Error([
10:08:27                      ^
10:08:27     
10:08:27     Error: Timeout (10000) while waiting for /(?:assert|break|break on start|debugCommand|exception|other|promiseRejection) in/i; found: < Debugger ending on ws://127.0.0.1:9229/0161d4a8-8f01-4590-b7e9-18412e6e9a13
10:08:27     < For help, see: https://nodejs.org/en/docs/inspector
10:08:27     < 
10:08:27     debug> 
10:08:27     
10:08:27     < Debugger listening on ws://127.0.0.1:9229/f8ab1b5e-afa3-4a18-8975-1d76592e7ade
10:08:27     < For help, see: https://nodejs.org/en/docs/inspector
10:08:27     < 
10:08:27     
10:08:27     debug> 
10:08:27     
10:08:27     connecting to 127.0.0.1:9229 ...
10:08:27      ok
10:08:27     
10:08:27     debug> 
10:08:27     
10:08:27     < Debugger attached.
10:08:27     < 
10:08:27     debug> 
10:08:27         at Timeout.<anonymous> (/home/iojs/build/workspace/node-test-binary-arm/test/common/debugger.js:84:18)
10:08:27         at listOnTimeout (node:internal/timers:557:17)
10:08:27         at processTimers (node:internal/timers:500:7)
10:08:27     
10:08:27     Node.js v17.0.0-pre
10:08:27   ...

@nodejs-github-bot
Copy link
Collaborator

@artur-ma
Copy link

Should be any semver label here? (minor/major)

@mcollina mcollina added semver-minor PRs that contain new features and should be released in the next minor version. author ready PRs that have at least one approval, no pending requests for changes, and a CI started. and removed needs-ci PRs that need a full CI run. labels Sep 19, 2021
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina
Copy link
Member

Landed in 4e8f11d

mcollina pushed a commit that referenced this pull request Sep 19, 2021
Fixes: #40071
PR-URL: #40082
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
@mcollina mcollina closed this Sep 19, 2021
BethGriggs pushed a commit that referenced this pull request Sep 21, 2021
Fixes: #40071
PR-URL: #40082
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
BethGriggs added a commit that referenced this pull request Sep 21, 2021
Notable changes:

crypto:
  * (SEMVER-MINOR) add rsa-pss keygen parameters (Filip Skokan) #39927
doc:
  * add Ayase-252 to collaborators (Qingyu Deng) #40078
fs:
  * (SEMVER-MINOR) make `open` and `close` stream override optional when unused (Antoine du Hamel) #40013
http:
  * (SEMVER-MINOR) limit requests per connection (Artur K) #40082
src:
  * (SEMVER-MINOR) add --no-global-search-paths cli option (Cheng Zhao) #39754
  * (SEMVER-MINOR) add option to disable global search paths (Cheng Zhao) #39754
  * (SEMVER-MINOR) make napi_create_reference accept symbol (JckXia) #39926
stream:
  * (SEMVER-MINOR) add signal support to pipeline generators (Robert Nagy) #39067

PR-URL: TODO
BethGriggs pushed a commit that referenced this pull request Sep 21, 2021
Fixes: #40071
PR-URL: #40082
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
BethGriggs added a commit that referenced this pull request Sep 21, 2021
Notable changes:

crypto:
  * (SEMVER-MINOR) add rsa-pss keygen parameters (Filip Skokan) #39927
doc:
  * add Ayase-252 to collaborators (Qingyu Deng) #40078
fs:
  * (SEMVER-MINOR) make `open` and `close` stream override optional when unused (Antoine du Hamel) #40013
http:
  * (SEMVER-MINOR) limit requests per connection (Artur K) #40082
src:
  * (SEMVER-MINOR) add --no-global-search-paths cli option (Cheng Zhao) #39754
  * (SEMVER-MINOR) add option to disable global search paths (Cheng Zhao) #39754
  * (SEMVER-MINOR) make napi_create_reference accept symbol (JckXia) #39926
stream:
  * (SEMVER-MINOR) add signal support to pipeline generators (Robert Nagy) #39067

PR-URL: TODO
@BethGriggs BethGriggs mentioned this pull request Sep 21, 2021
1 task
BethGriggs added a commit that referenced this pull request Sep 22, 2021
Notable changes:

crypto:
  * (SEMVER-MINOR) add rsa-pss keygen parameters (Filip Skokan) #39927
doc:
  * add Ayase-252 to collaborators (Qingyu Deng) #40078
fs:
  * (SEMVER-MINOR) make `open` and `close` stream override optional when unused (Antoine du Hamel) #40013
http:
  * (SEMVER-MINOR) limit requests per connection (Artur K) #40082
src:
  * (SEMVER-MINOR) add --no-global-search-paths cli option (Cheng Zhao) #39754
  * (SEMVER-MINOR) add option to disable global search paths (Cheng Zhao) #39754
  * (SEMVER-MINOR) make napi_create_reference accept symbol (JckXia) #39926
stream:
  * (SEMVER-MINOR) add signal support to pipeline generators (Robert Nagy) #39067

PR-URL: #40175
BethGriggs added a commit that referenced this pull request Sep 22, 2021
Notable changes:

crypto:
  * (SEMVER-MINOR) add rsa-pss keygen parameters (Filip Skokan) #39927
doc:
  * add Ayase-252 to collaborators (Qingyu Deng) #40078
fs:
  * (SEMVER-MINOR) make `open` and `close` stream override optional when unused (Antoine du Hamel) #40013
http:
  * (SEMVER-MINOR) limit requests per connection (Artur K) #40082
src:
  * (SEMVER-MINOR) add --no-global-search-paths cli option (Cheng Zhao) #39754
  * (SEMVER-MINOR) add option to disable global search paths (Cheng Zhao) #39754
  * (SEMVER-MINOR) make napi_create_reference accept symbol (JckXia) #39926
stream:
  * (SEMVER-MINOR) add signal support to pipeline generators (Robert Nagy) #39067

PR-URL: #40175
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. http Issues or PRs related to the http subsystem. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Max requests per socket
6 participants