You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多Gunicorn Worker环境下崩溃重启时保留共享数据的方案

Gunicorn崩溃重启时跳过共享目录清理的方案

这里提供几个实用方案,帮你区分Gunicorn的正常启动/手动重启和崩溃重启,从而决定是否清理/tmp/user_data目录:

方案1:基于PID文件的进程状态检查

通过记录主进程PID,重启时验证PID对应的进程是否存活,判断是否为崩溃重启:

  1. 编写启动脚本,核心逻辑:
    • 检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:18:32