emostar / express-graceful-exit Goto Github PK
View Code? Open in Web Editor NEWGracefully exit Express in order to get zero downtime deploys
License: MIT License
Gracefully exit Express in order to get zero downtime deploys
License: MIT License
../../node_modules/express-graceful-exit/index.d.ts:4:1 - error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.
4 namespace GracefulExit {
Seeing this error in our app. Hard to reproduce. We handle more traffic than an average site. Fix looks simple.
TypeError: Cannot read property 'length' of undefined
at Timeout._onTimeout (/media/ephemeral0/fc-2017-app/release-build-583/node_modules/express-graceful-exit/lib/graceful-exit.js:121:38)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
As specify in doc, socketio is a Configuration option.
But is missing in
express-graceful-exit/index.d.ts
Line 5 in 818ef9a
Any chance that exports.gracefulExitHandler could take a callback?
The default behaviour (if callback not supplied) could be to call process.exit when the server closes, but it would be handy to callback to the user for the user to perform any further orderly shutdown tasks.
https://github.com/huntharo/express-graceful-exit-test has a test application that shows that express-graceful-exit
will, depending on the number of open sockets at the time of shutdown, either sever a socket and exit immediately after receiving a request OR (worse) sever the socket but run any received requests on all sockets except for the last one open. This second scenario could likely result in transactions committed to databases that the caller is not directly informed about and that might have been retried as a result of the connection being closed (this may then cause the retry to fail if the already running transaction is still open).
There does not appear to be any reading of the HTTP 1.1 spec that would support the current behavior and it does not appear that the proposed fix can make things worse as the current behavior is unpredictable as to whether any individual request will run or be dropped during the shutdown process. The fix makes it 100% predictable that all requests will be started during shutdown, but if they take longer than the suicideTimeout then they may be terminated before finishing.
Hat tip to #9 for having the right fix for a different problem description (closed without merging... I think they determined their originally reported problem was actually working correctly).
https://github.com/huntharo/express-graceful-exit-test
This application demonstrates an issue with express-graceful-exit
which connections are abruptly terminated after receiving a request on an existing connection during the graceful exit period. This abrupt termination looks the same as the application crashing and will generally be handled by HTTP-level load balancers as something that they should generate a 5xx-level error for (or close their incoming corresponding connection).
This application is also used to test that the fix for the issue works correctly.
Connection close in a response header signals to the caller that the connection will have been closed after the response bytes have been sent, meaning that the connection can no longer be used to send additional requests. This is similar to the way that HTTP 1.0 worked by default.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example,
Connection: close
in either the request or the response header fields indicates that the connection SHOULD NOT be considered `persistent' (section 8.1) after the current request/response is complete.
express-graceful-exit
sees there are no more connectionsprocess.exit()
is called and the request effectively does not runexpress-graceful-exit
will force-close it in around 60 seconds)node --version
- 10.x is confirmed to work with this applicationexpress-graceful-exit
cd ..
git clone [email protected]:emostar/express-graceful-exit.git
cd express-graceful-exit
npm install
cd express-graceful-exit-test
npm install
express-graceful-exit
cd express-graceful-exit-test
npm link ../express-graceful-exit
curl
would do by defaultnpm run start
to start the app as this changes signal handling behaviorcd express-graceful-exit-test
node index.js
telnet localhost 3000
GET /sleep HTTP/1.1
, press [enter] twicecd express-graceful-exit
git checkout 6eba1de
npm run start
to start the app as this changes signal handling behaviorcd express-graceful-exit-test
node index.js
telnet localhost 3000
GET /sleep HTTP/1.1
, press [enter] twicekill -SIGTERM [PID]
node
GET /sleep HTTP/1.1
, press [enter] twiceConnection: close
header valuecd express-graceful-exit
git checkout 6eba1de
npm run start
to start the app as this changes signal handling behaviorcd express-graceful-exit-test
node index.js
telnet localhost 3000
GET /sleep HTTP/1.1
, press [enter] twicetelnet localhost 3000
kill -SIGTERM [PID]
node
GET /sleep HTTP/1.1
, press [enter] twiceConnection: close
header valuecd express-graceful-exit
lib/graceful-exit.js
req.connection.setTimeout(1);
res.set('Connection', 'close');
npm run start
to start the app as this changes signal handling behaviorcd express-graceful-exit-test
node index.js
telnet localhost 3000
GET /sleep HTTP/1.1
, press [enter] twicekill -SIGTERM [PID]
node
GET /sleep HTTP/1.1
, press [enter] twiceConnection: close
header valueThe express-graceful-exit
library does a lot of the heavy lifting to setup to be able to gracefully close all connections. However, setting the timeout on the connection to 1 ms after a request is received causes both the ability to run and finish requests without being able to tell the caller that they succeeded or failed and the dropping of received requests without running them.
Gracefully handling shutdown requires processing any last incoming requests and sending their responses, or responding to them, without running them, with an HTTP-level status code indicating that they can be retried (there is, unfortunately, no such code with 429 and 503 and Retry-After response header being the closest matches).
It is a very minor change to express-graceful-exit
to allow it to correctly handle both scenarios reproduced above.
I understand wanting to set exitProcess
to false to handle shutdown in a custom manner. However, I was surprised to find that doing so also disables the suicide shutdown. I would consider those two things to be separate, as in "I'll handle closing everything myself, but I would still like shutdown to happen after 2 minutes if clean up is not done by then."
It's simple enough to implement a custom suicide routine, but obviously it would be nicer if this package handled it automatically.
Is suicide shutdown being tied to exitProcess
intentional, or an oversight?
Can you get 0.4.2 published to npm please. ๐ธ
It is not up there
The current NPM package does not contain index.d.ts
, it will be great if you publish a new version :-)
I'm opening this mostly to start a discussion and kick around some ideas. I've noticed that when the express server is shutting down and getting requests the handleFinalRequests function is logging the headers which could include sensitive information like an API token.
We are providing our own bunyan logger instance method (either info
or error
method).
A couple of ideas on how we could deal with this:
gracefulExitHandler
function could take a new option which is a callback function to scrub header values for logging which by default would just return the headers object back untouched (or a copy of it really so it's not modified by reference, that's probably better to not cause issues with downstream middleware).header
property and scrub is as necessary before passing it on to the underlying logger (bunyan in our case).A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.