Skip to content

Commit 1f21ad9

Browse files
authored
Merge pull request #85 from blushingpenguin/node-timeout
disable keep alive timeout, headers timeout and log any server timeouts
2 parents 5956ab2 + 259780e commit 1f21ad9

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

Changelog.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ This project uses [semantic versioning](http://semver.org/spec/v2.0.0.html). Ref
33
*[Semantic Versioning in Practice](https://www.jering.tech/articles/semantic-versioning-in-practice)*
44
for an overview of semantic versioning.
55

6-
## [Unreleased](https://github.com/JeringTech/Javascript.NodeJS/compare/5.4.1...HEAD)
6+
## [Unreleased](https://github.com/JeringTech/Javascript.NodeJS/compare/5.4.2...HEAD)
7+
8+
## [5.4.2](https://github.com/JeringTech/Javascript.NodeJS/compare/5.4.1...5.4.2) - Jun 25, 2020
9+
### Fixes
10+
- Disabled unecessary Node.js HTTP timeouts, added logging for timeouts. ([#85](https://github.com/JeringTech/Javascript.NodeJS/pull/85)).
711

812
## [5.4.1](https://github.com/JeringTech/Javascript.NodeJS/compare/5.4.0...5.4.1) - Jun 23, 2020
913
### Fixes

src/NodeJS/Javascript/Servers/OutOfProcess/Http/HttpServer.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var Module = require('module');
33
import * as path from 'path';
44
import * as http from 'http';
55
import * as stream from 'stream';
6-
import { AddressInfo } from 'net';
6+
import { AddressInfo, Socket } from 'net';
77
import InvocationRequest from '../../../InvocationData/InvocationRequest';
88
import ModuleSourceType from '../../../InvocationData/ModuleSourceType';
99

@@ -26,9 +26,29 @@ let projectDir = process.cwd();
2626
// Create server
2727
const server = http.createServer(serverOnRequestListener);
2828

29-
// In Node.js v13+ this is the default, however for earlier versions it is 120 seconds.
29+
// The timeouts below are designed to manage network instability. Since we're using the HTTP protocol on a local machine, we can disable them
30+
// to avoid their overhead and stability issues.
31+
32+
// By default, on older versions of Node.js, request handling times out after 120 seconds.
33+
// This timeout is disabled by default on Node.js v13+.
34+
// Becuase of the older versions, we explicitly disable it.
3035
server.setTimeout(0);
3136

37+
// By default, a socket is destroyed if it receives no incoming data for 5 seconds: https://nodejs.org/api/http.html#http_server_keepalivetimeout.
38+
// This is good practice when making external requests because DNS records may change: https://github.com/dotnet/runtime/issues/18348.
39+
// Since we're using the HTTP protocol on a local machine, it's safe and more efficient to keep sockets alive indefinitely.
40+
server.keepAliveTimeout = 0;
41+
42+
// By default, a socket is destroyed if its incoming headers take longer than 60 seconds: https://nodejs.org/api/http.html#http_server_headerstimeout.
43+
// In early versions of Node.js, even if setTimeout() was specified with a non-zero value, the server would wait indefinitely for headers.
44+
// This timeout was added to deal with that issue. We specify setTimeout(0), so this timeout is of no use to us.
45+
//
46+
// Note that while 0 disables this timeout in node 12.17+, in earlier versions it causes requests to time out immediately, so set to 10 years.
47+
server.headersTimeout = 10 * 365 * 24 * 60 * 60 * 1000;
48+
49+
// Log timed out connections for debugging
50+
server.on('timeout', serverOnTimeout);
51+
3252
// Send client error details to client for debugging
3353
server.on('clientError', serverOnClientError);
3454

@@ -182,6 +202,12 @@ function serverOnClientError(error: Error, socket: stream.Duplex) {
182202
socket.end(httpResponseMessage);
183203
}
184204

205+
// Send timeout details to client for debugging - this shouldn't fire but there have been various node http server timeout issues in the past.
206+
// The socket won't actually get closed (the timeout function needs to do that manually).
207+
function serverOnTimeout(socket: Socket) {
208+
console.error(`Ignoring unexpected socket timeout for address ${socket.remoteAddress}, port ${socket.remotePort}`);
209+
}
210+
185211
function serverOnListeningListener() {
186212
// Signal to HttpNodeHost which loopback IP address (IPv4 or IPv6) and port it should make its HTTP connections on
187213
// and that we are ready to process invocations.

0 commit comments

Comments
 (0)