| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1942,18 +1942,39 @@ added: v8.0.0 | |||
| 1942 | 1942 | ||
| 1943 | 1943 | The number of milliseconds of inactivity a server needs to wait for additional | |
| 1944 | 1944 | incoming data, after it has finished writing the last response, before a socket | |
| 1945 | - will be destroyed. If the server receives new data before the keep-alive | ||
| 1946 | - timeout has fired, it will reset the regular inactivity timeout, i.e., | ||
| 1947 | - [`server.timeout`][]. | ||
| 1945 | + will be destroyed. | ||
| 1946 | + | ||
| 1947 | + This timeout value is combined with the | ||
| 1948 | + \[`server.keepAliveTimeoutBuffer`]\[] option to determine the actual socket | ||
| 1949 | + timeout, calculated as: | ||
| 1950 | + socketTimeout = keepAliveTimeout + keepAliveTimeoutBuffer | ||
| 1951 | + If the server receives new data before the keep-alive timeout has fired, it | ||
| 1952 | + will reset the regular inactivity timeout, i.e., [`server.timeout`][]. | ||
| 1948 | 1953 | ||
| 1949 | 1954 | A value of `0` will disable the keep-alive timeout behavior on incoming | |
| 1950 | 1955 | connections. | |
| 1951 | - A value of `0` makes the http server behave similarly to Node.js versions prior | ||
| 1956 | + A value of `0` makes the HTTP server behave similarly to Node.js versions prior | ||
| 1952 | 1957 | to 8.0.0, which did not have a keep-alive timeout. | |
| 1953 | 1958 | ||
| 1954 | 1959 | The socket timeout logic is set up on connection, so changing this value only | |
| 1955 | 1960 | affects new connections to the server, not any existing connections. | |
| 1956 | 1961 | ||
| 1962 | + ### `server.keepAliveTimeoutBuffer` | ||
| 1963 | + | ||
| 1964 | + <!-- YAML | ||
| 1965 | + added: REPLACEME | ||
| 1966 | + --> | ||
| 1967 | + | ||
| 1968 | + * Type: {number} Timeout in milliseconds. **Default:** `1000` (1 second). | ||
| 1969 | + | ||
| 1970 | + An additional buffer time added to the | ||
| 1971 | + [`server.keepAliveTimeout`][] to extend the internal socket timeout. | ||
| 1972 | + | ||
| 1973 | + This buffer helps reduce connection reset (`ECONNRESET`) errors by increasing | ||
| 1974 | + the socket timeout slightly beyond the advertised keep-alive timeout. | ||
| 1975 | + | ||
| 1976 | + This option applies only to new incoming connections. | ||
| 1977 | + | ||
| 1957 | 1978 | ### `server[Symbol.asyncDispose]()` | |
| 1958 | 1979 | ||
| 1959 | 1980 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,6 +25,7 @@ const { | |||
| 25 | 25 | ArrayIsArray, | |
| 26 | 26 | Error, | |
| 27 | 27 | MathMin, | |
| 28 | + NumberIsFinite, | ||
| 28 | 29 | ObjectKeys, | |
| 29 | 30 | ObjectSetPrototypeOf, | |
| 30 | 31 | ReflectApply, | |
@@ -184,8 +185,6 @@ const kConnections = Symbol('http.server.connections'); | |||
| 184 | 185 | const kConnectionsCheckingInterval = Symbol('http.server.connectionsCheckingInterval'); | |
| 185 | 186 | ||
| 186 | 187 | const HTTP_SERVER_TRACE_EVENT_NAME = 'http.server.request'; | |
| 187 | - // TODO(jazelly): make this configurable | ||
| 188 | - const HTTP_SERVER_KEEP_ALIVE_TIMEOUT_BUFFER = 1000; | ||
| 189 | 188 | ||
| 190 | 189 | class HTTPServerAsyncResource { | |
| 191 | 190 | constructor(type, socket) { | |
@@ -484,6 +483,14 @@ function storeHTTPOptions(options) { | |||
| 484 | 483 | this.keepAliveTimeout = 5_000; // 5 seconds; | |
| 485 | 484 | } | |
| 486 | 485 | ||
| 486 | + const keepAliveTimeoutBuffer = options.keepAliveTimeoutBuffer; | ||
| 487 | + if (keepAliveTimeoutBuffer !== undefined) { | ||
| 488 | + validateInteger(keepAliveTimeoutBuffer, 'keepAliveTimeoutBuffer', 0); | ||
| 489 | + this.keepAliveTimeoutBuffer = keepAliveTimeoutBuffer; | ||
| 490 | + } else { | ||
| 491 | + this.keepAliveTimeoutBuffer = 1000; | ||
| 492 | + } | ||
| 493 | + | ||
| 487 | 494 | const connectionsCheckingInterval = options.connectionsCheckingInterval; | |
| 488 | 495 | if (connectionsCheckingInterval !== undefined) { | |
| 489 | 496 | validateInteger(connectionsCheckingInterval, 'connectionsCheckingInterval', 0); | |
@@ -546,6 +553,13 @@ function Server(options, requestListener) { | |||
| 546 | 553 | } | |
| 547 | 554 | ||
| 548 | 555 | storeHTTPOptions.call(this, options); | |
| 556 | + | ||
| 557 | + // Optional buffer added to the keep-alive timeout when setting socket timeouts. | ||
| 558 | + // Helps reduce ECONNRESET errors from clients by extending the internal timeout. | ||
| 559 | + // Default is 1000ms if not specified. | ||
| 560 | + const buf = options.keepAliveTimeoutBuffer; | ||
| 561 | + this.keepAliveTimeoutBuffer = | ||
| 562 | + (typeof buf === 'number' && NumberIsFinite(buf) && buf >= 0) ? buf : 1000; | ||
| 549 | 563 | net.Server.call( | |
| 550 | 564 | this, | |
| 551 | 565 | { allowHalfOpen: true, noDelay: options.noDelay ?? true, | |
@@ -1012,9 +1026,10 @@ function resOnFinish(req, res, socket, state, server) { | |||
| 1012 | 1026 | } | |
| 1013 | 1027 | } else if (state.outgoing.length === 0) { | |
| 1014 | 1028 | if (server.keepAliveTimeout && typeof socket.setTimeout === 'function') { | |
| 1015 | - // Increase the internal timeout wrt the advertised value to reduce | ||
| 1029 | + // Extend the internal timeout by the configured buffer to reduce | ||
| 1016 | 1030 | // the likelihood of ECONNRESET errors. | |
| 1017 | - socket.setTimeout(server.keepAliveTimeout + HTTP_SERVER_KEEP_ALIVE_TIMEOUT_BUFFER); | ||
| 1031 | + // This allows fine-tuning beyond the advertised keepAliveTimeout. | ||
| 1032 | + socket.setTimeout(server.keepAliveTimeout + server.keepAliveTimeoutBuffer); | ||
| 1018 | 1033 | state.keepAliveTimeoutSet = true; | |
| 1019 | 1034 | } | |
| 1020 | 1035 | } else { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,39 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + const http = require('http'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + | ||
| 7 | + const server = http.createServer(common.mustCall((req, res) => { | ||
| 8 | + const body = 'buffer test\n'; | ||
| 9 | + | ||
| 10 | + res.writeHead(200, { 'Content-Length': body.length }); | ||
| 11 | + res.write(body); | ||
| 12 | + res.end(); | ||
| 13 | + })); | ||
| 14 | + | ||
| 15 | + server.keepAliveTimeout = 100; | ||
| 16 | + | ||
| 17 | + if (server.keepAliveTimeoutBuffer === undefined) { | ||
| 18 | + server.keepAliveTimeoutBuffer = 1000; | ||
| 19 | + } | ||
| 20 | + assert.strictEqual(server.keepAliveTimeoutBuffer, 1000); | ||
| 21 | + | ||
| 22 | + server.listen(0, () => { | ||
| 23 | + http.get({ | ||
| 24 | + port: server.address().port, | ||
| 25 | + path: '/', | ||
| 26 | + }, (res) => { | ||
| 27 | + res.resume(); | ||
| 28 | + server.close(); | ||
| 29 | + }); | ||
| 30 | + }); | ||
| 31 | + | ||
| 32 | + { | ||
| 33 | + const customBuffer = 3000; | ||
| 34 | + const server = http.createServer(() => {}); | ||
| 35 | + server.keepAliveTimeout = 200; | ||
| 36 | + server.keepAliveTimeoutBuffer = customBuffer; | ||
| 37 | + assert.strictEqual(server.keepAliveTimeoutBuffer, customBuffer); | ||
| 38 | + server.close(); | ||
| 39 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments