如何使用asyncio实现后台运行的会话保活守护方法?
现有实现存在的问题
- 事件循环提前退出:
keep_alive_task协程仅创建了keep_alive后台任务就直接返回,loop.run_until_complete检测到主协程执行完毕后会直接终止事件循环,后台保活任务没有机会持续运行。 - 同步调用阻塞事件循环:
self.send基于同步requests库实现,直接在async协程中调用会阻塞整个事件循环,不仅会导致保活间隔计时不准,还会卡死后续所有异步任务的执行。 - 事件循环获取时机错误:装饰器
async_loop在函数定义阶段就调用asyncio.get_event_loop()获取事件循环,若你在非主线程实例化Session,会触发线程无默认事件循环的报错。 - 初始化逻辑永久阻塞:
__init__中直接调用被async_loop装饰的keep_alive_task,会导致Session实例化的步骤永久卡住,后续业务代码完全无法执行。
修正后的实现方案
如果必须保留requests同步调用的实现,可以通过线程池包裹同步逻辑避免阻塞事件循环,以下是可正常运行的守护保活实现:
import asyncio import requests import threading from concurrent.futures import ThreadPoolExecutor # 全局线程池用于运行同步requests请求 executor = ThreadPoolExecutor(max_workers=1) class Session: def __init__(self): # 为每个Session创建独立的事件循环 self.loop = asyncio.new_event_loop() # 保活逻辑放到守护线程运行,不阻塞初始化流程 threading.Thread(target=self._run_keep_alive_loop, daemon=True).start() # 原有send逻辑不变 def send(self, msg): return requests.post("你的请求地址", json=msg).json() # 封装同步send为异步调用,避免阻塞事件循环 async def async_send(self, msg): return await self.loop.run_in_executor(executor, self.send, msg) async def keep_alive(self): while True: keep_alive_message = { "janus": "keepalive", } response = await self.async_send(keep_alive_message) print(response) await asyncio.sleep(30) async def keep_alive_task(self): asyncio.create_task(self.keep_alive()) # 永久挂起主协程,避免事件循环提前退出 await asyncio.Event().wait() def _run_keep_alive_loop(self): asyncio.set_event_loop(self.loop) self.loop.run_until_complete(self.keep_alive_task())
内容的提问来源于stack exchange,提问作者MONTASER ABDMAJID ZEHRI
相关产品推荐
相关产品推荐

