GeezerVison is showing github.com — http: add Agent.agentKeepAliveTimeoutBuffer option · nodejs/node@6ae202f
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/http.md +10Lines changed: 10 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -116,6 +116,10 @@ http.get({ | 116 | 116 | <!-- YAML | 117 | 117 | added: v0.3.4 | 118 | 118 | changes: | | 119 | + - version: | | 120 | + - REPLACEME | | 121 | + pr-url: https://github.com/nodejs/node/pull/59315 | | 122 | + description: Add support for `agentKeepAliveTimeoutBuffer`. | 119 | 123 | - version: | 120 | 124 | - v24.5.0 | 121 | 125 | pr-url: https://github.com/nodejs/node/pull/58980 | @@ -156,6 +160,12 @@ changes: | 156 | 160 | the [initial delay][] | 157 | 161 | for TCP Keep-Alive packets. Ignored when the | 158 | 162 | `keepAlive` option is `false` or `undefined`. **Default:** `1000`. | | 163 | + * `agentKeepAliveTimeoutBuffer` {number} Milliseconds to subtract from | | 164 | + the server-provided `keep-alive: timeout=...` hint when determining socket | | 165 | + expiration time. This buffer helps ensure the agent closes the socket | | 166 | + slightly before the server does, reducing the chance of sending a request | | 167 | + on a socket that’s about to be closed by the server. | | 168 | + **Default:** `1000`. | 159 | 169 | * `maxSockets` {number} Maximum number of sockets to allow per host. | 160 | 170 | If the same host opens multiple concurrent connections, each request | 161 | 171 | will use new socket until the `maxSockets` value is reached. | |
Collapse file Copy file name to clipboardExpand all lines: lib/_http_agent.js +10-3Lines changed: 10 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 22 | 22 | 'use strict'; | 23 | 23 |
| 24 | 24 | const { | | 25 | + NumberIsFinite, | 25 | 26 | NumberParseInt, | 26 | 27 | ObjectKeys, | 27 | 28 | ObjectSetPrototypeOf, | @@ -60,8 +61,6 @@ const kOnKeylog = Symbol('onkeylog'); | 60 | 61 | const kRequestOptions = Symbol('requestOptions'); | 61 | 62 | const kRequestAsyncResource = Symbol('requestAsyncResource'); | 62 | 63 |
| 63 | | -// TODO(jazelly): make this configurable | 64 | | -const HTTP_AGENT_KEEP_ALIVE_TIMEOUT_BUFFER = 1000; | 65 | 64 | // New Agent code. | 66 | 65 |
| 67 | 66 | // The largest departure from the previous implementation is that | @@ -114,6 +113,14 @@ function Agent(options) { | 114 | 113 | this.scheduling = this.options.scheduling || 'lifo'; | 115 | 114 | this.maxTotalSockets = this.options.maxTotalSockets; | 116 | 115 | this.totalSocketCount = 0; | | 116 | + | | 117 | + this.agentKeepAliveTimeoutBuffer = | | 118 | + typeof this.options.agentKeepAliveTimeoutBuffer === 'number' && | | 119 | + this.options.agentKeepAliveTimeoutBuffer >= 0 && | | 120 | + NumberIsFinite(this.options.agentKeepAliveTimeoutBuffer) ? | | 121 | + this.options.agentKeepAliveTimeoutBuffer : | | 122 | + 1000; | | 123 | + | 117 | 124 | const proxyEnv = this.options.proxyEnv; | 118 | 125 | if (typeof proxyEnv === 'object' && proxyEnv !== null) { | 119 | 126 | this[kProxyConfig] = parseProxyConfigFromEnv(proxyEnv, this.protocol, this.keepAlive); | @@ -559,7 +566,7 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) { | 559 | 566 | if (hint) { | 560 | 567 | // Let the timer expire before the announced timeout to reduce | 561 | 568 | // the likelihood of ECONNRESET errors | 562 | | - let serverHintTimeout = (NumberParseInt(hint) * 1000) - HTTP_AGENT_KEEP_ALIVE_TIMEOUT_BUFFER; | | 569 | + let serverHintTimeout = (NumberParseInt(hint) * 1000) - this.agentKeepAliveTimeoutBuffer; | 563 | 570 | serverHintTimeout = serverHintTimeout > 0 ? serverHintTimeout : 0; | 564 | 571 | if (serverHintTimeout === 0) { | 565 | 572 | // Cannot safely reuse the socket because the server timeout is | |
Collapse file Copy file name to clipboard +44Lines changed: 44 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const assert = require('assert'); | | 5 | +const http = require('http'); | | 6 | + | | 7 | +// Ensure agentKeepAliveTimeoutBuffer option sets the correct value or falls back to default. | | 8 | +{ | | 9 | + const agent1 = new http.Agent({ agentKeepAliveTimeoutBuffer: 1500, keepAlive: true }); | | 10 | + assert.strictEqual(agent1.agentKeepAliveTimeoutBuffer, 1500); | | 11 | + | | 12 | + const agent2 = new http.Agent({ agentKeepAliveTimeoutBuffer: -100, keepAlive: true }); | | 13 | + assert.strictEqual(agent2.agentKeepAliveTimeoutBuffer, 1000); | | 14 | + | | 15 | + const agent3 = new http.Agent({ agentKeepAliveTimeoutBuffer: Infinity, keepAlive: true }); | | 16 | + assert.strictEqual(agent3.agentKeepAliveTimeoutBuffer, 1000); | | 17 | + | | 18 | + const agent4 = new http.Agent({ keepAlive: true }); | | 19 | + assert.strictEqual(agent4.agentKeepAliveTimeoutBuffer, 1000); | | 20 | +} | | 21 | + | | 22 | +// Integration test with server sending Keep-Alive timeout header. | | 23 | +{ | | 24 | + const SERVER_TIMEOUT = 3; | | 25 | + const BUFFER = 1500; | | 26 | + | | 27 | + const server = http.createServer((req, res) => { | | 28 | + res.setHeader('Keep-Alive', `timeout=${SERVER_TIMEOUT}`); | | 29 | + res.end('ok'); | | 30 | + }); | | 31 | + | | 32 | + server.listen(0, common.mustCall(() => { | | 33 | + const agent = new http.Agent({ agentKeepAliveTimeoutBuffer: BUFFER, keepAlive: true }); | | 34 | + assert.strictEqual(agent.agentKeepAliveTimeoutBuffer, BUFFER); | | 35 | + | | 36 | + http.get({ port: server.address().port, agent }, (res) => { | | 37 | + res.resume(); | | 38 | + res.on('end', () => { | | 39 | + agent.destroy(); | | 40 | + server.close(); | | 41 | + }); | | 42 | + }); | | 43 | + })); | | 44 | +} |
|