はじめに
この記事では、Expressアプリケーションに graceful shutdown(優雅な終了処理)を設定する方法について手を動かして勉強します。
実装
3秒後にレスポンスを返す、エンドポイントを用意しました。
クライアント側からは、以下のcurlを実行することで、3秒後にレスポンスを取得できます。
リクエストの途中でサーバを落としてみる
forループで10回リクエストを投げます。
まずはじめにgraceful shutdownをしないで実行します。
ターミナルの左側でexpressを実行し、右側でリクエストを投げてみます。
expressをrequestID: 3
が出たあと、サーバを停止します。
右側でcurlを実行してた方は、レスポンスを待たずにEmpty Reploy from server
が返ってきました。
続いて、graceful shutdownのコードで実行してみます。
今度はrequestID 3
の後にサーバを落としても、curlでリクエストした方は、{"response": "3"}
が返ってきました。
closeの仕様を確認する
server.close()
を呼んでいますが、closeはどういった仕様なのでしょうか?
型定義のコメントを読むと、以下のことがわかります。
- closeが呼び出されると、新規コネクションの受付を停止する
- 既存の接続は維持する
- すべての接続が終了すると、サーバが終了し、‘close’イベントを発生させる
- callbackは’close’イベントが発生した時に一度だけ実行される
- callbackの’Error’は、サーバをcloseするとき、openでない場合に発生する
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9a6a0cdd493eecf71c2d5d428d3b7ba28574af70/types/node/net.d.ts#L525-L534
実装はこちら
https://github.com/nodejs/node/blob/c311dc43cd2579ecb3c9f86a802899e6aa163dae/lib/net.js#L2147-L2184
つまり、先ほどの話では、requestID = 3 は実行中だったのでレスポンスを返したが、requestID = 4 以降は新規コネクションだったためエラーになったということですね。
今回使ったコードはblog-code/2023/04/express-graceful-shutdown/に置いています。
補足
process.on(event, listener)
のeventにはNodeJS.Signalsを指定できます。
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9a6a0cdd493eecf71c2d5d428d3b7ba28574af70/types/node/process.d.ts#L53-L90
Expressのapp.listen()
から作成したserverは、nodeのhttp.Serverを作成しています。
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9a6a0cdd493eecf71c2d5d428d3b7ba28574af70/types/node/http.d.ts#L235-L238
types/node/net.d.tsに書いてあるServerクラス
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9a6a0cdd493eecf71c2d5d428d3b7ba28574af70/types/node/net.d.ts#L472
参考