You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI-Kubernetes执行耗时函数导致存活探针失败的解决方案求助

问题解决:FastAPI耗时任务阻塞健康探针端点

问题根源

你的insights_func是同步阻塞函数,当它执行时会占用FastAPI的事件循环,导致所有后续请求(包括/healthz存活探针请求)无法被处理。Kubernetes存活探针超时后就会触发Pod重启。

解决方案

以下是几种无需调整探针超时,就能保证/healthz始终可响应的方案:

方案1:将耗时任务移到后台执行(立即返回响应)

使用FastAPI的BackgroundTasks把同步任务放到后台线程执行,端点立即返回响应,事件循环不会被阻塞。

修改后的代码:

from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
import utils.logger as custom_log
from src.insights import insights_func

# 初始化logger(根据你的实际情况调整)
log = custom_log.get_logger()

@app.get('/healthz', include_in_schema=False)
async def return_ok_status():
    return JSONResponse(content={"status": "All Good!"}, status_code=200)

# 封装耗时任务,供后台执行
def run_insights_task():
    try:
        insights_func()
        log.info("daily_checkup task finished successfully")
    except Exception as e:
        log.error("daily_checkup task failed: %s", str(e))

@app.get("/daily_checkup")
async def daily_checkup_status(background_tasks: BackgroundTasks):
    log.info("daily_checkup endpoint triggered")
    background_tasks.add_task(run_insights_task)
    # 返回202表示任务已接受并开始执行
    return JSONResponse(content={"status": "Daily checkup task started"}, status_code=202)

方案2:用线程池执行同步任务(等待任务完成后返回)

如果需要等待任务完成再返回结果,但不想阻塞事件循环,可使用asyncio.to_thread(Python 3.9+)将同步函数放到单独线程执行:

修改后的代码:

import asyncio
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
import utils.logger as custom_log
from src.insights import insights_func

log = custom_log.get_logger()

@app.get('/healthz', include_in_schema=False)
async def return_ok_status():
    return JSONResponse(content={"status": "All Good!"}, status_code=200)

@app.get("/daily_checkup")
async def daily_checkup_status():
    log.info("daily_checkup endpoint triggered")
    try:
        # 将同步函数委托给线程池执行,不阻塞事件循环
        await asyncio.to_thread(insights_func)
        return JSONResponse(content={"status": "No stuck jobs!"}, status_code=200)
    except Exception as e:
        log.error("An error occurred: %s", str(e))
        raise HTTPException(status_code=500, detail="Internal Server Error")

方案3:将业务函数改为异步(最优解)

如果可以修改insights_func,将其重构为异步函数(比如用异步HTTP客户端、异步数据库驱动等),从根源避免阻塞事件循环。这是最优雅的方案,但需要调整业务代码实现。

关键说明

以上方案都能保证事件循环不被耗时任务占用,/healthz端点可以随时响应Kubernetes的探针请求,无需修改探针超时配置。

内容的提问来源于stack exchange,提问作者Amodon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:14:51