Gunicornでコードを一回だけ実行する
Gunicorn を起動すると、マスタープロセスと指定された数のワーカープロセスが起動される。
複数のワーカープロセスが起動され、あるコードを一回だけ実行したい場合は、server hook を使用する。
例えば on_starting
フックを利用し、マスタープロセスが起動される前に呼び出されるため、コードの実行は一回だけで済む。
on_starting
以外、pre_fork
と post_fork
も利用できる。
- pre_fork はワーカープロセスがフォークされる前に呼び出される。
- post_fork はワーカープロセスがフォークされた後に呼び出される。
フォークされたワーカーの数を記録し、そして post_fork でワーカーの数を確認し、1 であればコードを実行する。
import gunicorn.app.base
from flask import Flask
def create_app():
app = Flask(__name__)
...
return app
class StandaloneApplication(gunicorn.app.base.BaseApplication):
worker_num = 0
@classmethod
def pre_fork(cls, server, worker):
server.log.info('Ready to fork a new worker...')
cls.worker_num += 1
@classmethod
def post_fork(cls, server, worker):
server.log.info(f'{cls.worker_num} workers have been forked.')
if cls.worker_num == 1:
...
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
self.options['pre_fork'] = self.pre_fork
self.options['post_fork'] = self.post_fork
super().__init__()
def load_config(self):
config = {key: value for key, value in self.options.items()
if key in self.cfg.settings and value is not None}
for key, value in config.items():
self.cfg.set(key.lower(), value)
def load(self):
return self.application
if __name__ == '__main__':
app = create_app()
options = {
'bind': '127.0.0.1:5000',
'workers': '4',
'log-level': 'debug',
}
StandaloneApplication(app, options).run()