FastAPI中用asyncio.run()启动后台任务后无法访问API及Swagger的咨询
问题原因
你调用asyncio.run(startup())后,代码会卡在这一行永远执行下去——因为startup函数里的asyncio.gather(*tasks)会等待所有监控任务完成,而每个monitor函数都是无限循环,永远不会结束。这就导致后面的uvicorn.run()根本没机会执行,API服务自然无法启动。
解决方案
改用FastAPI的启动事件钩子来启动后台任务,同时把同步的HTTP请求换成异步实现,避免阻塞事件循环:
- 使用
@app.on_event("startup")装饰器标记启动时要执行的函数,FastAPI会在服务启动后自动运行它,且不会阻塞主线程。 - 替换
requests库为异步HTTP客户端aiohttp,因为同步请求会卡住整个异步事件循环。
修正后的完整代码
首先安装依赖:
pip install aiohttp
代码:
import asyncio import aiohttp from fastapi import FastAPI app = FastAPI() monitor_data = [ {"url": "https://endpoint_1/", "type": "https", "Interval": 30}, {"url": "https://endpoint_2/", "type": "https", "Interval": 60} ] @app.get('/') async def amialive(): return "Live" async def monitor(url, interval): async with aiohttp.ClientSession() as session: while True: try: async with session.get(url) as response: print(f"{url}: {response.status_code}") except Exception as e: print(f"{url} 请求失败: {str(e)}") await asyncio.sleep(interval) @app.on_event("startup") async def startup(): for data in monitor_data: url = data["url"] interval = data["Interval"] # 创建后台任务,无需等待完成 asyncio.create_task(monitor(url, interval)) if __name__ == "__main__": import uvicorn uvicorn.run("network_monitoring:app", host="0.0.0.0", port=8000, reload=True)
说明
@app.on_event("startup")装饰的函数会在FastAPI服务启动后异步执行,不会阻塞API端点的运行。- 使用
asyncio.create_task创建监控任务后直接返回,不需要await asyncio.gather,这样启动函数会立即完成,不会卡住。 aiohttp的异步请求保证了监控任务不会阻塞事件循环,API和后台任务可以同时正常工作。
内容的提问来源于stack exchange,提问作者Praveen K M
相关产品推荐
相关产品推荐

