flask进程收到sigterm后丢请求,因开发服务器不处理信号,而gunicorn等若未配--graceful-timeout和--timeout,会强制终止worker中断正在处理的请求,尤其影响长耗时或流式响应。

Flask进程收到SIGTERM后为什么还会丢请求
因为默认情况下,Flask开发服务器(app.run())不处理系统信号,而生产环境用的WSGI服务器(如Gunicorn、uWSGI)虽能响应SIGTERM,但若未配置优雅停机,会立即终止worker进程,正在处理的请求会被强制中断——尤其是长耗时或流式响应场景。
Gunicorn中启用graceful timeout的关键配置
用Gunicorn部署时,仅靠--timeout不够,它控制单个请求最大执行时间;真正决定“是否等现有请求结束再退出”的是--graceful-timeout和--timeout的配合:
-
--graceful-timeout 30:收到SIGTERM后,最多等待30秒让worker自然完成当前请求 -
--timeout 120:单个请求超时强制杀掉,防止某个卡死请求拖垮整个停机流程 -
--workers 4 --preload:避免--preload缺失导致信号无法广播到所有worker
启动命令示例:gunicorn --bind :8000 --graceful-timeout 30 --timeout 120 --workers 4 --preload app:app
在Flask应用内监听SIGTERM并清理资源
仅靠WSGI服务器不够,业务逻辑里常有数据库连接、缓存客户端、后台线程等需主动关闭。Flask本身无内置信号钩子,需手动注册:
import signal
import sys
from flask import Flask
<p>app = Flask(<strong>name</strong>)
db_conn = None # 示例:全局DB连接</p><p>def cleanup():
if db_conn:
db_conn.close()
print("Cleanup done.")</p><p>def handle_sigterm(signum, frame):
print(f"Received {signum}, shutting down gracefully...")
cleanup()
sys.exit(0)</p><p>signal.signal(signal.SIGTERM, handle_sigterm)</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill9386" title="python学习"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20e695c2374.jpg" alt="python学习" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill9386" title="python学习" class="overflowclass">python学习</a>
<p class="overflowclass">Python 编程学习助手 skill,面向零基础用户。 当用户表达以下意图时触发: - 学习 Python 基础概念(变量、数据类型、循环、函数、类等) - 请求 Python 练习题或测验 - 请求审查或调试 Python 代码 - 请求 Python 项目实战指导(爬虫、数据分析、Web 开发等入门项目) - 泛化表述如"教我 Python""我想学编程""Python 怎么写""帮我学 Python" 此 skill</p>
</div>
<a rel="nofollow" href="/xiazai/skill9386" title="python学习" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
注意:sys.exit(0)必须显式调用,否则Gunicorn可能因worker未退出而强行kill,绕过--graceful-timeout。
反向代理(如Nginx)配合健康检查规避502
即使后端已优雅停机,Nginx若在worker退出瞬间转发新请求,仍会返回502 Bad Gateway。解决方式是让Nginx先标记服务为不可用:
- 在停机前,调用一个内部
/health接口返回503,并配Nginxhealth_check或自定义upstream状态管理 - 或使用
nginx -s reload临时移除该server,再发SIGTERM(适合滚动发布) - 避免依赖
proxy_next_upstream error自动重试——它对502重试不保证幂等,可能造成重复提交
最简实践:停机脚本里先curl -X POST http://localhost:8000/shutdown(触发cleanup() + os.kill(os.getpid(), signal.SIGTERM)),再等几秒由Gunicorn收尾。
真正难的是长连接和流式响应——它们占用worker时间远超普通HTTP请求,--graceful-timeout必须设得比最长可能响应时间更宽裕,否则照样被强杀。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










