Gunicorn多Worker启动Flask时delete脚本重复执行,需仅单次运行
解决Gunicorn多Worker模式下脚本仅执行一次的问题
问题原因
用gunicorn -w 4 -b 127.0.0.1:4004 test:app启动服务时,Gunicorn会创建4个独立的Worker子进程。你的代码中全局调用了manager()函数,每个Worker进程启动时都会执行这个函数,进而触发delete脚本运行,最终导致脚本被重复执行4次。
解决方案
方案1:使用Gunicorn的--preload参数
这是最简洁的解决方式,让Gunicorn在主进程中预先加载Flask应用,再fork出Worker进程。这样全局初始化代码只会在主进程执行一次,所有Worker共享已初始化的应用状态。
修改启动命令为:
gunicorn --preload -w 4 -b 127.0.0.1:4004 test:app
代码无需额外修改,原有的manager()全局调用会在主进程仅执行一次,Worker进程是fork生成的,不会重复执行全局初始化逻辑。
方案2:用文件锁确保单进程执行脚本
如果无法使用--preload(比如存在进程不安全的初始化操作),可以通过文件锁机制,保证只有第一个启动的Worker进程执行脚本:
修改后的完整代码如下:
import multiprocessing import subprocess import os import sys from flask import Flask, request from flask_restful import Resource, Api from module.delete import run import logging import fcntl logging.basicConfig( format='[%(levelname)s][%(asctime)s][PID %(process)d]: (%(filename)s) %(message)s', level=logging.INFO) app = Flask(__name__) api = Api(app) ports = { 'prod': 4004, 'ppr': 4004, 'dev': 4004 } def run_delete_script(): # 创建文件锁,确保只有一个进程执行脚本 lock_file = '/tmp/delete_script.lock' with open(lock_file, 'w') as f: try: # 获取排他锁,非阻塞模式 fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB) config = run() config.run() logging.info("Delete脚本执行完成") except BlockingIOError: # 其他进程已持有锁,跳过执行 logging.info("Delete脚本已被其他进程执行,当前进程跳过") # 在应用初始化阶段执行一次 run_delete_script() class Test(Resource): logging.info(f"Resource = {Resource}") def post(self): return {'message': 'Payload stored successfully'}, 200 api.add_resource(Test, '/testing') if __name__ == '__main__': env = 'master' if len(sys.argv) == 1 else sys.argv[1] app.run(port=ports.get(env, 4004))
方案3:判断Gunicorn主进程执行脚本
通过检查进程关系,只让Gunicorn的主进程执行脚本:
def run_delete_script(): # 仅当当前进程是Gunicorn主进程时执行 if 'gunicorn' in os.path.basename(sys.argv[0]): # Worker进程的父进程是Gunicorn主进程,判断当前PID是否等于父PID if os.getpid() != os.getppid(): return config = run() config.run() run_delete_script()
注意事项
- 使用
--preload时,避免在全局初始化中创建进程不安全的资源(如数据库连接、Socket连接),这些资源会被Worker进程继承,可能导致连接异常。 - 文件锁方案需要确保锁文件所在目录有写入权限,服务重启时锁会自动释放,无需手动清理。
内容的提问来源于stack exchange,提问作者titirsha tsi
相关产品推荐
相关产品推荐

