地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Nginx】graceful shutdown

Gracefull shutdownってどういう実装なの?

グレースフルシャットダウンの定義を以下とするなら

  • 停止指示後に、新しい接続を受付しない
  • 残った処理中の接続が完了するのを待ってから、プロセスを安全に停止する

TCPレイヤでやることとしたらlisten socketをcloseする。 -> 新規接続を受付しない

子プロセスは親から受けたシグナルを元に処理完了で終了するように実装する -> 安全停止

といった流れになる。Nginxをサンプルにみてみる(めちゃめちゃ端折ってます)

static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
    for ( ;; ) {
        // SIG_QUITを受け取った子プロセスは以下に入る
        if (ngx_quit) {
            ngx_quit = 0;
            ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                          "gracefully shutting down");
            ngx_setproctitle("worker process is shutting down");

            if (!ngx_exiting) {
                ngx_exiting = 1;  // 終了フラグを立てる
                ngx_set_shutdown_timer(cycle); // shutdownタイマーを設定する
                ngx_close_listening_sockets(cycle); // リスニングソケットをcloseする
                ngx_close_idle_connections(cycle); // アイドルコネクションをcloseする
            }
        }
        // 終了フラグが立っているので以下に入る
        if (ngx_exiting) {
            if (ngx_event_no_timers_left() == NGX_OK) { // ngx_event_no_timers_leftはアクティブな接続がある限りはOKにならない
                ngx_worker_process_exit(cycle);  // 終了関数を呼び出す
            }
        }
    }
}

ngx_event_no_timers_leftがactiveな接続を監視してなければプロセスが終了する。読んでいて気づいたがこれはバックエンドのアプリのどこかで刺さった場合はNginx自体のこの処理もTimeoutを設定してなければ永遠に動かない実装の模様。そもそもそんなのアプリ側でなんとかしろよって話だけどいつかハマりそう。ngx_event_no_timers_leftはこの辺

ngx_int_t
ngx_event_no_timers_left(void)
{
    ngx_event_t        *ev;
    ngx_rbtree_node_t  *node, *root, *sentinel;

    sentinel = ngx_event_timer_rbtree.sentinel;
    root = ngx_event_timer_rbtree.root;

    if (root == sentinel) {
        return NGX_OK;
    }

    for (node = ngx_rbtree_min(root, sentinel);
         node;
         node = ngx_rbtree_next(&ngx_event_timer_rbtree, node))
    {
        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));

        if (!ev->cancelable) {
            return NGX_AGAIN;
        }
    }

    return NGX_OK;
}

nginx.org