如何让Flask在终止前等待所有请求处理完成?
实现Flask优雅停机:等待当前请求完成后终止
默认用flask run启动的开发服务器,收到终止信号(比如Ctrl+C触发的SIGINT)时会直接退出,不会等待正在处理的请求(比如大文件下载)完成。要实现优雅停机,可通过以下两种方案解决:
方案1:基于信号捕获的开发环境实现
通过捕获终止信号,标记应用进入维护模式拦截新请求,同时等待现有请求处理完成后再关闭服务器,代码实现如下:
from flask import Flask, abort import signal import time from werkzeug.serving import run_simple app = Flask(__name__) # 标记是否允许接收新请求 allow_new_requests = True @app.route("/download") def download_large_file(): # 模拟大文件下载的耗时逻辑 print("开始处理大文件下载请求...") time.sleep(10) return "大文件内容".encode("utf-8") @app.before_request def block_new_requests(): """拦截新请求,返回维护提示""" global allow_new_requests if not allow_new_requests: abort(503, description="服务器正在停机维护,请稍后再试") def handle_shutdown(signum, frame): global allow_new_requests print("\n收到停机信号,启动优雅停机流程...") # 停止接收新请求 allow_new_requests = False print("已停止接收新请求,等待现有请求处理完成...") # 根据业务最长请求耗时调整等待时长 time.sleep(15) print("现有请求处理完毕,服务器退出") exit(0) if __name__ == "__main__": # 捕获Ctrl+C触发的SIGINT信号 signal.signal(signal.SIGINT, handle_shutdown) # 用Werkzeug的run_simple启动,和flask run行为一致 run_simple("localhost", 5000, app, threaded=True)
核心逻辑
- 用
signal模块捕获终止信号,触发优雅停机流程 - 通过全局变量+
before_request钩子拦截新请求,返回503状态码 - 设置等待时长,确保正在处理的请求有足够时间完成
方案2:生产环境用支持优雅停机的服务器(推荐)
生产环境不建议使用Flask自带的开发服务器,推荐用Gunicorn这类原生支持优雅停机的WSGI服务器:
- 启动命令:
gunicorn --workers=2 --timeout=120 app:app - 触发优雅停机:执行
kill -TERM <Gunicorn主进程ID>,或直接按Ctrl+C,Gunicorn会自动等待worker处理完当前请求后再退出
关键配置参数
--timeout:设置单个请求的最长处理时长,避免无限等待--graceful-timeout:自定义优雅停机的等待时长(默认30秒)
内容的提问来源于stack exchange,提问作者YiLuo
相关产品推荐
相关产品推荐

