Asyncio http server循环配置:非阻塞添加aiohttp到循环列表后服务无法启动
问题根因
核心问题是web.run_app的调用不符合多异步任务共用事件循环的场景要求:
web.run_app是同步阻塞函数,内部会独占事件循环运行直到服务终止,放在协程中直接调用会直接卡死当前异步调度逻辑,导致服务无法正常启动,其他异步任务也无法运行。- 你提前将
self.webLoop()协程实例放入数组中,第一次await asyncio.gather执行完成后该协程就会进入已结束状态,下次循环再次传入会直接抛出协程不可重用的报错。 - 新版本aiohttp已经废弃了在
web.Application构造时传入loop参数的写法,手动指定loop没有必要。 - 路由处理函数
webPing的第一个参数是aiohttp传入的请求对象,参数名写为handler属于不规范写法,不会影响运行但建议修正。
修复方案
使用aiohttp提供的AppRunner+TCPSite手动挂载服务,实现非阻塞和其他异步任务共同运行:
import asyncio import logging from aiohttp import web log = logging.getLogger(__name__) # 类内部方法示例 async def webPing(self, request): text = "OK" return web.Response(text=text) async def webLoop(self): self.app = web.Application() self.app.add_routes([web.get('/ping', self.webPing)]) # 手动初始化服务 runner = web.AppRunner(self.app) await runner.setup() site = web.TCPSite(runner, port=8080) await site.start() # 保持服务运行直到触发 shutdown 标记 while not self.shutdown: await asyncio.sleep(1) # 退出前清理服务资源 await runner.cleanup() async def runMe(self): while not self.shutdown: try: # 可在gather中同时添加其他需要并行的异步任务 await asyncio.gather( self.webLoop(), # 其他异步任务... ) except Exception as e: log.error(f'Unhandled exception in gather loop {e}') # 异常后延迟1秒再重启,避免无限快速报错占用资源 await asyncio.sleep(1)
内容的提问来源于stack exchange,提问作者Miro Krsjak
相关产品推荐
相关产品推荐

