uWSGI でファイルが更新された時にリロードする
最初は inotifyx 使って自力で書こうとしてたんだけど,ブロックしてうまくいかなかったりして,thread でも立てなきゃいけないのかなと思って uwsgidecorators を読んでたら,そもそも uwsgidecorators (というかそもそも uwsgi-core) にファイル更新検知機能がついてた。
メインとなる wsgi ファイルが main.wsgi
というファイル名だったとして,監視するモジュール((別モジュールだてにしなくてもいい (main.wsgi
に入れ込む) のかもしれないけど追ってない。追記: やってみたら別モジュールに独立させなくてもうまくいった。小さい捨て WSGI スクリプトであればリロードのロジックを入れ込むのが楽。(もちろん,WSGI アプリケーションとして独立させるなら入れ込まないほうがいいけど) )) watcher.py
は:
# watcher.py import uwsgi from uwsgidecorators import filemon @filemon('main.wsgi') def reloaded(num): uwsgi.reload()
対応する uWSGI のパラメータは,たとえば:
; uwsgi.ini [uwsgi] master = true plugins = python,http http = :8000 wsgi-file = main.wsgi import = watcher
ファイルがいっぱいあったらどうすんねーんと思うかもしれないけど,@filemon
デコレータは,ディレクトリの監視もできます。
ちなみに内的には inotify 機構を使っているので無駄はないはず。IN_ALL_EVENTS
レベルの監視をしてるんで,touch
とかしてもちゃんとリロードされます。
あと今回の話と関係ないけど,たとえば 1 分間リクエストがなかった場合にワーカーを自動的に kill するには
idle = 60
のようにしておけばよい。uWSGI 使うようなシチュエーションでそんなにメモリをケチるシーンはないかもしんないけど。
追記: idle
(や lazy
) と @filemon
の相性はよくないかもしんない。ワーカーがいない状態で編集してリクエスト投げたら編集前の内容だったことがあった。気のせいかもしれないけど。
もういっこわりと便利なオプションは harakiri
で
harakiri = 60
のようにしておくと,処理に 60 秒以上かかるワーカーは強制的に落とされます。