/health路由不应仅返回200,而应做轻量级依赖检查;/ready路由检查db、redis等就绪状态;需同步调低gunicorn timeout并增大k8s initialdelayseconds,配置校验应前置到create_app()中。

Flask里加/health路由别直接返回200
很多同学一上来就写@app.route('/health') + return 'OK',看似能用,但Kubernetes或Nginx健康检查会误判——它不关心内容,只看状态码。如果后端DB挂了、Redis连不上,这个接口照样返回200,探测就失去意义。
真正有效的存活探测得做轻量级依赖检查。常见做法是:查数据库连接是否可用、关键缓存是否可写、配置文件是否存在等。但注意别在这里做耗时操作(比如查10万条数据),否则探针超时失败。
- 用
try/except包裹关键依赖调用,失败则返回503 Service Unavailable - 避免在
/health里调用外部HTTP服务(如调第三方API),这会让探测变脆弱 - 不要记录日志或打点——高频探测会产生大量噪音
- 示例:
db.engine.execute('SELECT 1')比db.session.query(User).first()更轻量
用flask-healthz还是手写?看部署环境
flask-healthz确实省事,自动提供/healthz和/readyz,还支持自定义检查器。但它把逻辑封装太深,出问题时不好定位——比如某次升级后readyz突然卡住,你得翻源码才知道它默认检查了哪些东西。
如果你用Kubernetes,推荐手写两个独立路由:/health(liveness,只检查进程是否活着)和/ready(readiness,检查是否准备好接流量)。这样可以分开控制,比如DB恢复后/ready先通,但迁移脚本还在跑,/health就先别通。
-
/health:只检查Python进程、Gunicorn worker是否响应,甚至可以只return '', 200 -
/ready:才检查DB、Redis、必要配置项(如os.getenv('STRIPE_KEY')是否非空) - 别让
flask-healthz的Healthz类接管整个app实例,它会覆盖你的错误处理器
gunicorn健康检查超时导致K8s反复重启
Kubernetes默认livenessProbe超时是1秒,而Gunicorn默认timeout是30秒,但它的worker启动慢(尤其带SQLAlchemy初始化时),第一次/health请求可能卡在worker分配上,直接触发K8s杀进程。
这不是代码问题,是配置错配。必须同步调低Gunicorn的--timeout(建议设为5),同时在K8s里把initialDelaySeconds提到10秒以上,给应用冷启动留时间。
- 在
gunicorn.conf.py里明确写timeout = 5,别依赖默认值 - K8s的
livenessProbe至少设initialDelaySeconds: 10,timeoutSeconds: 2 - 用
curl -v http://localhost:8000/health手动测,看是不是真在2秒内返回 - 如果用了
gevent或eventlet,确认monkey patch已提前执行,否则time.sleep()会阻塞整个worker
别在/health里读配置文件或环境变量
看起来安全的操作,其实有坑:Docker镜像里/etc/config.yaml权限不对,或者os.getenv('DEBUG')返回None而不是字符串,都可能导致AttributeError或KeyError,整个健康接口崩掉——结果就是所有探针全挂,服务被当成宕机下线。
环境变量和配置文件属于“启动期依赖”,应该在Flaskcreate_app()里就校验并抛出明确错误,而不是拖到运行时靠健康检查来兜底。
- 把配置校验放在
create_app()函数开头,失败直接sys.exit(1),让容器启动失败,而不是启动后假装健康 -
/health路由里只做运行时检查(网络连通性、内存水位、队列长度等) - 如果真要读配置,用
os.getenv('XXX', '').strip()加防御式写法,别直接os.environ['XXX']
健康检查不是兜底机制,它是信号灯。灯亮不代表路没问题,只代表灯自己还亮着。最常被忽略的是:把本该在CI/CD阶段做的配置验证,挪到运行时靠/health硬扛。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











