萌えハッカーニュースリーダー

2025/05/04 21:09 Graceful Shutdown in Go: Practical Patterns

出典: https://victoriametrics.com/blog/go-graceful-shutdown/index.html
hakase
博士

やあ、ロボ子。今日はGo言語のGraceful Shutdownについて話すのじゃ。

roboko
ロボ子

Graceful Shutdown、ですか。アプリケーションを安全に終了させるためのものですよね。

hakase
博士

その通り!終了時に未完了のリクエストを処理して、リソースを安全に解放することが目的なのじゃ。具体的には、新規リクエストの受付停止、実行中のリクエストの完了待ち、そしてデータベース接続などのリソース解放が必要になるぞ。

roboko
ロボ子

なるほど。記事には、Unix系システムでのシグナルの捕捉についても書かれていますね。`SIGTERM`、`SIGINT`、`SIGHUP`といったシグナルが重要とのことですが。

hakase
博士

`SIGTERM`はKubernetesがPodを強制終了する前に送る終了要求、`SIGINT`は`Ctrl+C`でプロセスを止める時、`SIGHUP`は設定のリロードに使われるのじゃ。`os/signal`パッケージでこれらのシグナルを自分で処理できるぞ。

roboko
ロボ子

`signal.Notify`関数で特定のシグナルをチャネルに送信するようにGoランタイムに指示できるんですね。Go 1.16以降では、`signal.NotifyContext`でシグナル処理をコンテキストのキャンセルに関連付けられる、と。

hakase
博士

そうそう!そして、タイムアウトも重要じゃ。Kubernetesでは猶予期間がデフォルトで30秒あるからの。猶予期間の約20%を安全マージンとして確保することが推奨されてるのじゃ。

roboko
ロボ子

猶予期間内にリクエストの処理とリソースの解放を完了させる必要があるんですね。新規リクエストの受付停止には、`net/http`パッケージの`http.Server.Shutdown`メソッドが使えると。

hakase
博士

その通り!コンテナ環境だと、Podが終了してもトラフィックを受け続ける可能性があるから、KubernetesのReadiness Probeを使って、Podがトラフィックを受信できる状態かどうかを判断するのが良いのじゃ。

roboko
ロボ子

Readiness Probeを失敗させることで、オーケストレーターにPodがトラフィックを受信しないように指示するんですね。

hakase
博士

`server.Shutdown`関数は、全てのアクティブな接続が閉じられるか、タイムアウトした場合に戻るのじゃ。ハンドラーがシャットダウンを認識できるように、コンテキストを使う必要があるぞ。

roboko
ロボ子

コンテキストミドルウェアや`BaseContext`を使って、シャットダウンシグナルをリッスンするコンテキストでリクエストをラップするんですね。`context.Background()`や`time.Sleep()`など、コンテキストを無視する関数の使用は避けるべき、と。

hakase
博士

そう!終了シグナルを受信したらすぐにリソースを解放するのではなく、シャットダウンタイムアウトが経過するか、全てのリクエストが完了するまで待つのが大事じゃ。データベース接続は適切に閉じ、未完了のトランザクションはコミットまたはロールバックする必要があるぞ。

roboko
ロボ子

メッセージキューやブローカーもクリーンシャットダウンが必要になる場合があるんですね。外部サービスへの接続を手動で閉じることで、TCPタイムアウトを待つよりも早くシステムをクリーンアップできる、と。

hakase
博士

コンポーネントの初期化とは逆の順序でシャットダウンするのがオススメじゃ。Goの`defer`ステートメントを使うと、リソースの解放が簡単にできるぞ。

roboko
ロボ子

なるほど、Graceful Shutdownは奥が深いですね。今日の話、とても勉強になりました!

hakase
博士

ふむ、ロボ子も賢くなったの。褒美にアメをあげよう!…って、あれ?アメがない!

roboko
ロボ子

博士、またですか…。

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search