restart node.js forever process if response time too big - node.js

I got forever script for managing node.js site.
Sometimes node.js site hangs and response time go above 30 seconds. And in fact site is down. Then fast cure for it is restarting forever:
$ forever restart 3
where 3 is script number in forever list.
Is it possible to make it automatically? Is there option in forever which make it restart if response time will be more than 2 seconds for example?
Or maybe I got to run external script which will check response time and make descension to restart hanging forever script.
Or maybe I need to write this logic inside my node.js site?

I am assuming you want to restart the server if most of the reply are taking longer than x seconds. There are many tools that helps you to restart your instances based on their health. Monit is one of them. In this guide, monit restart the instance if reply doesn't come back in 10 seconds.
If you want to kill the instance if one request if any of the requests are taking too long, then you note down the time when you take in the request, and note down the time when request leaves. If the time is too long, throw an exception that you know will not get caught and the server would restart by itself. If you use express, then check the code for their logger under development mode, as it tracks the response time.

Aside leorex solution, I have something like this before to send 500 on timed out requests:
var writeHead = res.writeHead;
var timeout = setTimeout(function () {
res.statusCode = 500;
res.end('Response timed out');
// To avoid errors being thrown for writes after this, they should be ignored.
res.writeHead = res.write = res.end = function () {};
}, 40000);
res.writeHead = function () {
// This was called in time.
clearTimeout(timeout);
writeHead.apply(this, arguments);
};
You can use addTimeout module to take away the timeout clearing part.
Once you implemented, you can handle as you like, you can just call process.exit(1); so forever will immediately replaces you.
You can make this smarter. Also in my application, if an uncaught error happens, I signal the supervisor process so that it will spin up another worker process and gracefully go down(close http server and wait for all pending requests to finish). You can do the same in your application, but make sure everything has a timeout callback as a failover/backup plan.

Related

How do i build a node js program/service that stays alive in the background and performs a polling action every few seconds?

I'm looking for a way to build a node.js service that runs in the background and polls a Redis Stream (it could be anything really). While i understand how to build a web server in node.js, this "background service that stays alive and polls something (say invokes a REST endpoint or polls a msg queue) every few seconds" is something i have not been able to find. If you can show it in a few lines of code, that'll be awesome
Start an interval that to stuff every x seconds
startInterval() {
const x = 1;
setInterval(() => {
// Do your Stuff every x seconds here
}, 1000 * x)
},
You can achieve this with PM2.
It is an production process manager for deploying and daemonizing Node.js applications.
In combination with #BraveButter answer you should be able to do what you want.
You may be overthinking this, since Node server processes by default stay alive and actively respond to requests as events. This is in contrast to some server runtime architectures (such as PHP) that will by default have a process per request and so start
the script 'from scratch' for every new request.
So, in case you are being confused by PHP or somesuch, where you have to jump through extra hoops to create a persistent process, then bear in mind that you shouldn't have to do that for a simple Node server script. You can just set an interval that will run a function every so often using setInterval
You can use CronJS.
Basic Cron Usage from the doc :
var CronJob = require('cron').CronJob;
new CronJob('* * * * * *', function() {
console.log('You will see this message every second');
}, null, true, 'America/Los_Angeles');

node.js - after get request, script does not return to console

Here is a simple script
var http = require("http");
http.get( WEBSITE, function(res) {
console.log("Does not return");
return;
});
if WEBSITE variable is 'http://google.com' or 'http://facebook.com' script does not return to console.
but if WEBSITE variable is 'http://yahoo.com' or 'http://wikipedia.org' it returns to console. What is the difference?
By "return to console" I'm assuming you mean that node exits and drops you back at a shell prompt.
In fact, node does eventually exit for all of those domains you listed. (You were just impatient.)
What you are seeing is the result of HTTP keep-alives. By default, node keeps the TCP connection open after a HTTP request completes. This makes subsequent requests to the same server faster. As long as a TCP connection is still open, node will not exit.
Eventually, either node or the server will close the idle connection (and thus node will exit). It's likely that Google and Facebook allow idle connections to live for longer amounts of time than Yahoo and Wikipedia.
If you want your script to make a request and exit as soon as it completes, you need to disable HTTP keep-alives. You can do this by disabling Agent support.
http.get({ host:'google.com', port:80, path:'/', agent:false }, function(res) {
...
});
Only disable the Agent if you need this specific functionality. In a normal, long-running app, disabling the Agent can cause many problems.
There are also some other approaches you can take to avoid keep-alives keeping node running.

Shutting down a Node.js http server in a unit test

Supposed I have some unit tests that test a web server. For reasons I don't want to discuss here (outside scope ;-)), every test needs a newly started server.
As long as I don't send a request to the server, everything is fine. But once I do, a call to the http server's close function does not work as expected, as all made requests result in kept-alive connections, hence the server waits for 120 seconds before actually closing.
Of course this is not acceptable for running the tests.
At the moment, the only solutions I'd see was either
setting the keep-alive timeout to 0, so a call to close will actually close the server,
or to start each server on a different port, although this becomes hard to handle when you have lots of tests.
Any other ideas of how to deal with this situation?
PS: I had a asked How do I shutdown a Node.js http(s) server immediately? a while ago, and found a viable way to work around it, but as it seems this workaround does not run reliably in every case, as I am getting strange results from time to time.
function createOneRequestServer() {
var server = http.createServer(function (req, res) {
res.write('write stuff');
res.end();
server.close();
}).listen(8080);
}
You could also consider using process to fork processes and kill them after you have tested on that process.
var child = fork('serverModuleYouWishToTest.js');
function callback(signalCode) {
child.kill(signalCode);
}
runYourTest(callback);
This method is desirable because it does not require you to write special cases of your servers to service only one request, and keeps your test code and your production code 100% independant.

Efficient HTTP shutdown with keepalives?

This Node.js server will shutdown cleanly on a Ctrl+C when all connections are closed.
var http = require('http');
var app = http.createServer(function (req, res) {
res.end('Hello');
});
process.on('SIGINT', function() {
console.log('Closing...');
app.close(function () {
console.log('Closed.');
process.exit();
});
});
app.listen(3000);
The problem with this is that it includes keepalive connections. If you open a tab to this app in Chrome and then try to Ctrl+C it, it won't shutdown for about 2 minutes when Chrome finally releases the connection.
Is there a clean way of detecting when there are no more HTTP requests, even if some connections are still open?
By default there's no socket timeout, that means that connections will be open forever until the client closes them. If you want to set a timeout use this function: socket.setTimeout.
If you try to close the server you simply can't because there are active connections, so if you try to gracefully shutdown the shutdown function will hang up. The only way is to set a timeout and when it expires kill the app.
If you have workers it's not as simple as killing the app with process.exit(), so I made a module that does extacly what you're asking: grace.
You can hack some request tracking with the finish event on response:
var reqCount = 0;
var app = http.createServer(function (req, res) {
reqCount++;
res.on('finish', function() { reqCount--; });
res.end('Hello');
});
Allowing you to check whether reqCount is zero when you come to close the server.
The correct thing to do, though, is probably to not care about the old server and just start a new one. Usually the restart is to get new code, so you can start a fresh process without waiting for the old one to end, optionally using the child_process module to have a toplevel script managing the whole thing. Or even use the cluster module, allowing you to start the new process before you've even shut down the old one (since cluster manages balancing traffic between its child instances).
One thing I haven't actually tested very far, is whether it's guaranteed safe to start a new server as soon as server.close() returns. If not, then the new server could potentially fail to bind. There's an example in the server.listen() docs about how to handle such an EADDRINUSE error.

How to pause http server and resume it?

I'm trying to make simple http server, that can be pause and resume,, I've looked at Nodejs API,, here http://nodejs.org/docs/v0.6.5/api/http.html
but that couldn't help me,, I've tried to remove event listener on 'request' event and add back,, that worked well but the listen callback call increase every time i try to pause and resume,, here some code i did:
var httpServer = require('http').Server();
var resumed = 0;
function ListenerHandler(){
console.log('[-] HTTP Server running at 127.0.0.1:2525');
};
function RequestHandler(req,res){
res.writeHead(200,{'Content-Type': 'text/plain'});
res.end('Hello, World');
};
function pauseHTTP(){
if(resumed){
httpServer.removeAllListeners('request');
httpServer.close();
resumed = 0;
console.log('[-] HTTP Server Paused');
}
};
function resumeHTTP(){
resumed = 1;
httpServer.on('request',RequestHandler);
httpServer.listen(2525,'127.0.0.1',ListenerHandler);
console.log('[-] HTTP Server Resumed');
};
I don't know quite what you're trying to do, but I think you're working at the wrong level to do what you want.
If you want incoming connection requests to your web server to block until the server is prepared to handle them, you need to stop calling the accept(2) system call on the socket. (I cannot imagine that node.js, or indeed any web server, would make this task very easy. The request callback is doubtless called only when an entire well-formed request has been received, well after session initiation.) Your operating system kernel would continue accepting connections up until the maximum backlog given to the listen(2) system call. On slow sites, that might be sufficient. On busy sites, that's less than a blink of an eye.
If you want incoming connection requests to your web server to be rejected until the server is prepared to handle them, you need to close(2) the listening socket. node.js makes this available via the close() method, but that will tear down the state of the server. You'll have to re-install the callbacks when you want to run again.

Resources