Nodejs - How do you manage the fact that an error may crash the whole server

What are the best practices to deal with errors with nodejs? Is it documented somewhere?

One error, and the entire server may crash.

I have found the following:

  • a systemd config to restart the server after 1 second if it crashes. But this is not optimal it should never crash. But there may be a hole in the catch nets.
  • catch all code, and all promises to manage errors. This makes the code verbose but it helps and can be done well with practice.
  • implement an event callback onprocess exit to prevent the server from crashing. There I can clean up things like the database connection, and reset things without crashing. Since there is only once thread, we can manage the crach in one request so that it is clean for the next request. THis might not work with cluster mode that I am not using.

an incredibly broad topic.

The first step really is identifying possible error points in your code - normally this comes from user or external input to the system. Concatenating two strings you define in your code is never going to error, but reading a variable loaded from user input might.

It’s effectively Unit Testing.
“I have a function that relies upon 3 inputs. What happens if one of those inputs is… Cyrillic? Missing? A number? Out of bounds? Contains code?..”

If you start your app using a monitor such as forever, you can keep it running continuously and ensure that it automatically restarts if it exits unexpectedly.

Why would one use forever instead of systemd to keep node running?

Systemd is the default daemon manager on several Linux distributions.

Making the server restart is quite inneficient but it is better than nothing.

I am surprized that it is not better documented in nodejs for how to proceed with errors.

If you use Apache or Php, the request crashes but not the server.

Here is the exit handler mechanism that I have made. I allows to run cleanup functions, like closing sockets and database connections.

/*
source for catching exit events in Node.js:
http://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits
*/

module.exports = class ExitHandler {

  constructor() {
    const _this = this;

    //do something when app is closing
    process.on('exit',
               (code) => {
                 _this.exitHandler.bind(_this, {code: code, exit: true});
               });

    //catches ctrl+c event
    process.on('SIGINT', _this.exitHandler.bind(_this, {exit: true}));

    //catches uncaught exceptions
    process.on('uncaughtException', function(e) { _this.exitHandler.bind(_this, {exit:true}, e) });

    this.exitCallbacks = {};
  }

  exitHandler(options, err) {
    console.log("exit handler was called");

    if (err) {
      console.log(err.stack);
    }

    for (var key in this.exitCallbacks) {
      const callback = this.exitCallbacks[key];
      callback();
    }

    if (options.exit) {
      const code = options.code || 0;
      process.exit(code);
    }
  }

  registerExitCallback(callbackName, callback) {
    this.exitCallbacks[callbackName] = callback;
  }

  unregisterExitCallback(callbackName) {
    delete this.exitCallbacks[callbackName];
  }

  getExitCallback(callbackName) {
    return this.exitCallbacks[callbackName];
  }
}

I think I have found a good answer. The process.on(‘uncaughtException’, …) will make sure we get all possible exceptions without crashing the sever. But this is theoretical for me who has just found this. Has anyone tried it in practice?

process.on('uncaughtException', function(error) {
  // do something clever here
});

I was going to say that’s because Linux is not the only environment in which a server can be run, but then realized that you wouldn’t really want to run a server under any system other than Linux.

3 Likes

Ease of use, I guess. In the simplest case you just need to install it via npm and can then make an application run permanently with one command: forever app.js. For many people, that’s sufficient.

If you have systemd available (as Paul points out, forever can run on an OS other than Linux), configuring it is slightly more involved.

But forever was only an example. There are plenty of other packages out there which are used to start, daemonize and monitor your application. pm2 is quite a popular one - its cluster mode allows Node.js applications to be scaled across all available CPUs available, greatly increasing performance and reliability. I’m not sure how easy that would be to implement with systemd.

If it’s happening often it may be inefficient, but that’s indicative of a bigger problem that you’ll want to fix.

OK thank you for the info.

pm2 and other seem to be quite advanced and fine-tuned for node.js. systemd has the benefit of stability and of being integrated in the OS. I don’t know the answer for running a cluster of node.js processes with systemd. It is probably complex and inefficient. In Erlang, processes are supervised in an awesome way.

For the restart that is inefficient, when using process.on(‘uncaughtException’. …), one can grab errors without crashing the server, hence providing more avilability. You will fix the ground problem if you server crashes too often, but in the meantime, you server is much less available.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.