Flask+Gunicorn多Worker场景下如何仅执行一次启动初始化方法
解决Gunicorn多Worker下缓存重置重复执行的问题
针对多Worker环境下缓存重置逻辑执行多次的问题,这里提供三个无需队列工具的可行方案:
方案1:文件互斥锁(跨进程同步)
利用Unix系统的文件锁机制,让多个Worker竞争同一把锁,只有拿到锁的Worker执行缓存重置,其余跳过。这种方式不依赖Gunicorn版本,兼容性强。
import fcntl import os from flask import Flask def reset_cache(app): app.logger.info("Clearing cache") # 此处编写缓存清理与预热的具体逻辑 def create_app(test_config=None): app = Flask(__name__) # ... 你的其他配置代码 def safe_reset_cache(): lock_file_path = "/tmp/flask_cache_reset.lock" # 打开锁文件,不存在则创建 with open(lock_file_path, 'w') as lock_file: try: # 获取非阻塞排他锁,拿到锁则执行逻辑 fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB) reset_cache(app) except BlockingIOError: # 其他Worker已持有锁,跳过当前执行 app.logger.info("Cache reset already in progress, skipping") # 启动异步线程执行安全的缓存重置 t = threading.Thread(target=safe_reset_cache) t.start() return app
说明:文件锁会在进程结束后自动释放,残留的锁文件不影响下次启动,新进程可以重新获取锁。
方案2:基于Worker ID过滤(仅Gunicorn 20.0+可用)
Gunicorn 20.0及以上版本会为每个Worker设置GUNICORN_WORKER_ID环境变量,值从0开始递增。我们可以只让ID为0的Worker执行缓存重置逻辑:
import os from flask import Flask def reset_cache(app): app.logger.info("Clearing cache") # 缓存清理与预热逻辑 def create_app(test_config=None): app = Flask(__name__) # ... 你的其他配置代码 # 仅让第一个Worker(ID=0)执行缓存重置 worker_id = os.environ.get('GUNICORN_WORKER_ID') if worker_id == '0': t = threading.Thread(target=reset_cache, args=(app,)) t.start() return app
说明:这个方案代码最简洁,但需要确认你的Gunicorn版本符合要求。
方案3:通过Gunicorn配置文件在主进程执行
利用Gunicorn的pre_fork钩子,在主进程中执行一次缓存重置,所有Worker启动前就完成操作,从根源避免重复执行。
创建gunicorn_config.py配置文件:
def pre_fork(server, worker): # 导入你的应用模块与缓存重置函数 from your_app_module import create_app, reset_cache # 创建Flask应用并激活上下文 app = create_app() with app.app_context(): reset_cache(app)
启动Gunicorn时指定该配置文件:
gunicorn -w 4 --config gunicorn_config.py your_app_module:app
说明:该方案最可靠,因为逻辑在主进程执行,完全不会出现重复问题,适合服务器启动时的一次性初始化操作。
内容的提问来源于stack exchange,提问作者wowkin2
相关产品推荐
相关产品推荐

