web-dev-qa-db-ja.com

Express.jsでSIGINTを適切に処理する方法は?

Express.js サービスがSIGINTによって停止されたときに、いくつかの便利なことを行う必要があります。 Express.jsバージョン3.0.6を使用して、これが機能することを理解しています。

var express = require('express');

var app = express();
var server = app.listen(3000);

process.on('SIGINT', function() {
  console.log('Do something useful here.');
  server.close();
});

しかし、SIGINT(を発行しない限り、プロセスはBashプロンプトを返しません。Control-C)2回:

$ node problem.js 
^CDo something useful here.
^CDo something useful here.

net.js:1046
    throw new Error('Not running');
          ^
Error: Not running
    at Server.close (net.js:1046:11)
    at process.<anonymous> (/path/to/problem.js:8:10)
    at process.EventEmitter.emit (events.js:93:17)
    at SignalWatcher.startup.processSignalHandlers.process.on.process.addListener.w.callback (node.js:486:45)
$

もう1つの注意点。このExpress.jsサービスを開始し、リクエストを送信しない場合SIGINTは正しく終了します。

明らかに、私がここで見逃している基本的な何かがありますか?

23
Jacob Marble

SIGINTハンドラーをキャッチすることで、プロセスを終了するデフォルトの動作を防ぐことができます。 2回目に_Ctrl+C_を使用すると、_server.close_がキャッチされない例外をスローするため、プロセスが終了します。

SIGINTハンドラーの最後にprocess.exit()を追加するだけで、プロセスを正常に終了できます。

29
nneonneo

質問が完全に(または正しく)答えられておらず、人々がまだこの答えを見つける可能性があるため、オールディーズを復活させる。

あなたの質問の重要な部分は次のとおりです。

もう1つの注意点。このExpress.jsサービスを開始し、リクエストを送信しない場合、SIGINTは正しく終了します。明らかに、ここで欠落している基本的なものがありますか? `

不足しているのは、デフォルトでExpressが再利用のために接続を開いたままにする(HTTPキープアライブ)ことです。したがって、(最近の)リクエストがあった場合でも、イベントループに何かがあり、それがアプリが閉じない理由です。

process.exit()を使用することは機能しますが、別の^ Cを送信するようなものであり、他に何かが開いているという事実(データベース接続など)を隠す可能性があります。イベントループに何も残っていない場合は、アプリを閉じる必要があります。

そこで、例を変更して、接続に5秒のキープアライブを設定し、妥当な時間内に正常にシャットダウンするようにしました。

var express = require('express');

var serverPort = 3000;
var app = express();
var server = app.listen(serverPort);


// HTTP Keep-Alive to a short time to allow graceful shutdown
server.on('connection', function (socket) {
  socket.setTimeout(5 * 1000);
});

// Handle ^C
process.on('SIGINT', shutdown);

// Do graceful shutdown
function shutdown() {
  console.log('graceful shutdown express');
  server.close(function () {
    console.log('closed express');
  });
}

console.log('running server: http://localhost:' + serverPort);
8
Whyhankee

私はこのコードを使用しています:

server.close(() => {
  process.exit(0)
})
8
Kirill Gusyatin