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

FastAPI中如何在服务关闭时终止无限循环?

FastAPI服务关闭时终止路由中的无限循环

根路由/包含一个无限循环(实际场景为WebSocket长连接),按下CTRL+C停止服务时,shutdown事件无法触发,服务永久挂起。原代码中全局变量running始终为True,导致循环无法终止。

问题原因

Uvicorn在收到终止信号后,会先等待所有活跃的请求任务执行完成,才会触发FastAPI的shutdown事件。而路由中的无限循环任务一直未结束,导致shutdown事件永远无法执行,形成死锁。

解决方案

方案1:监听请求任务的取消事件(推荐)

异步任务在服务关闭时会收到asyncio.CancelledError,捕获该异常即可终止循环,这是异步场景下的标准处理方式:

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/")
async def index():
    try:
        while True:
            await asyncio.sleep(0.1)
            # 实际场景中可替换为WebSocket消息处理逻辑
    except asyncio.CancelledError:
        # 执行清理操作,比如关闭WebSocket连接、释放资源
        print("请求任务被取消,终止循环")
        raise  # 必须重新抛出异常,让FastAPI完成正常收尾

方案2:注册信号处理器直接修改状态

通过监听系统终止信号(SIGINT/SIGTERM),直接修改运行状态变量,避免依赖FastAPI的shutdown事件:

from fastapi import FastAPI
import asyncio
import signal
from contextvars import ContextVar

app = FastAPI()
# 使用ContextVar保证线程安全,避免信号处理器在非主线程运行时的变量冲突
running = ContextVar('running', default=True)

def handle_shutdown(signum, frame):
    running.set(False)

# 注册信号处理器,处理Ctrl+C和服务终止信号
signal.signal(signal.SIGINT, handle_shutdown)
signal.signal(signal.SIGTERM, handle_shutdown)

@app.get("/")
async def index():
    while running.get():
        await asyncio.sleep(0.1)

测试验证

  • 以uvicorn module.filename:app --host 0.0.0.0启动服务;
  • 使用curl http://ip:port/发起请求;
  • 按下CTRL+C,服务会正常终止,不会挂起。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 02:17:24