TornadoでGraceful Shutdownを実装する

概要

Tornadoでシグナルハンドラを使ってGraceful Shutdownを実装する方法を紹介しています。

Graceful Shutdownとは

リクエストを処理している最中にプロセスを突然停止してしまうと、そのリクエストは正常なレスポンスを返せずエラーになってしまいます。他にも、メモリ上に保持しているデータが失われたり、接続しているコンポーネントにコネクションが残ってしまったりします。

すべてのリクエストを完了させたり、データの永続化したり、リソースを解放してからプロセスを停止することを graceful shutdown といいます。(gracefulには「優雅な」や「上品な」という意味があります)

実装

シグナルハンドラ shutdown_handlerSIGTERM, SIGINT に対して設定します。

実際の終了処理 shutdown は既存のリクエストを阻害しないようにIOループの中で実行するようにしています。

import asyncio
import logging
import signal

import tornado.ioloop


async def shutdown():
    # リクエストを受けないようにする(readinessを落とすなど)
    logging.info('Change status for maintenance.')

    # すべてのリクエストが完了するまで待つ
    logging.info('Wait to complete requests.')
    await asyncio.sleep(1)

    # リソースの解放などの終了処理を実行する
    logging.info('Release resources.')

    tornado.ioloop.IOLoop.current().stop()


def shutdown_handler(sig, frame):
    logging.debug(f'Add callback for shutdown by signal {sig}.')
    tornado.ioloop.IOLoop.instance().add_callback_from_signal(shutdown)


def main():
    signal.signal(signal.SIGTERM, shutdown_handler)
    signal.signal(signal.SIGINT, shutdown_handler)

    logging.basicConfig(level=logging.DEBUG)

    # ここでApplicationの設定をする

    tornado.ioloop.IOLoop.current().start()


if __name__ == '__main__':
    main()

server.py を起動して Ctrl+CSIGINT を発生させて動作確認をします。

まとめ

Tornadoでシグナルハンドラを使ってGraceful Shutdownを実装する方法を紹介しました。

参考

コメントする