多Gunicorn Worker环境下崩溃重启时保留共享数据的方案
Gunicorn崩溃重启时跳过共享目录清理的方案
这里提供几个实用方案,帮你区分Gunicorn的正常启动/手动重启和崩溃重启,从而决定是否清理/tmp/user_data目录:
方案1:基于PID文件的进程状态检查
通过记录主进程PID,重启时验证PID对应的进程是否存活,判断是否为崩溃重启:
- 编写启动脚本,核心逻辑:
- 检查PID文件是否存在,若存在则验证PID对应的进程是否还在运行
- 进程不存在 → 崩溃重启,跳过清理
- 进程存在/无PID文件 → 正常启动/手动重启,执行清理
- 启动Gunicorn时写入PID文件,正常退出时删除该文件
示例启动脚本:
#!/bin/bash PID_FILE="/tmp/gunicorn_main.pid" DATA_DIR="/tmp/user_data" # 检查进程状态 if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") # 验证PID是否存活(kill -0仅检查进程存在,不发送信号) if ! kill -0 "$PID" 2>/dev/null; then echo "检测到崩溃重启,跳过数据清理" else rm -rf "$DATA_DIR"/* fi else # 首次启动,清理数据 rm -rf "$DATA_DIR"/* fi # 启动Gunicorn并写入PID gunicorn --pid "$PID_FILE" your_app:app # 正常退出时删除PID文件 rm -f "$PID_FILE"
方案2:基于健康状态文件的钩子判断
利用Gunicorn的信号钩子,正常启动时创建健康文件,正常退出时删除;崩溃时文件保留,以此作为判断依据:
示例Python代码(自定义Gunicorn应用):
from gunicorn.app.base import BaseApplication import os import signal DATA_DIR = "/tmp/user_data" HEALTH_MARK_FILE = "/tmp/gunicorn_healthy" class CustomGunicorn(BaseApplication): def __init__(self, app, opts=None): self.options = opts or {} self.app = app super().__init__() def load_config(self): for k, v in self.options.items(): if k in self.cfg.settings: self.cfg.set(k.lower(), v) def load(self): return self.app def handle_normal_exit(signum, frame): # 正常退出时删除健康标记文件 if os.path.exists(HEALTH_MARK_FILE): os.remove(HEALTH_MARK_FILE) # 转发信号让Gunicorn正常退出 os.kill(os.getpid(), signum) def main(): # 判断是否为崩溃重启 if not os.path.exists(HEALTH_MARK_FILE): # 首次启动/正常重启,清理数据 for file in os.listdir(DATA_DIR): os.remove(os.path.join(DATA_DIR, file)) else: print("检测到崩溃重启,跳过数据清理") # 创建健康标记文件 open(HEALTH_MARK_FILE, 'w').close() # 注册正常退出信号处理 signal.signal(signal.SIGTERM, handle_normal_exit) signal.signal(signal.SIGINT, handle_normal_exit) # 启动Gunicorn gunicorn_opts = { 'workers': 4, 'bind': '0.0.0.0:8000' } CustomGunicorn(your_app, gunicorn_opts).run() if __name__ == "__main__": main()
方案3:利用Systemd服务状态判断(适用于Systemd管理场景)
如果用Systemd托管Gunicorn服务,可以通过systemctl is-failed命令判断上次服务是否崩溃,在启动前执行条件清理:
修改Systemd服务文件(/etc/systemd/system/gunicorn.service):
[Unit] Description=Gunicorn Service After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/path/to/your/app # 启动前判断:上次服务失败则跳过清理,否则执行清理 ExecStartPre=/bin/bash -c 'if systemctl is-failed gunicorn.service >/dev/null 2>&1; then echo "崩溃重启,跳过清理"; else rm -rf /tmp/user_data/*; fi' ExecStart=/usr/bin/gunicorn --workers 4 --bind unix:/tmp/gunicorn.sock your_app:app Restart=always [Install] WantedBy=multi-user.target
内容的提问来源于stack exchange,提问作者Pranjal Doshi
相关产品推荐
相关产品推荐

