Teams bot无法并发接收消息问题咨询
问题描述
我用Python的aiohttp实现了一个Teams机器人,用的是Azure Bot的免费版,目前是作为自定义应用导入Teams里测试的。功能本身是正常的,但遇到一个问题:如果有多个人差不多同时给机器人发消息,机器人没法并发处理所有消息。
举个例子:同事发了一条消息,我紧接着也发了一条。看日志能看到同事的消息在处理,但我的消息要等他的处理完了,机器人才会收到。
不过我直接给API发并发消息是没问题的,中间不经过Teams的话就正常。
想请教两个问题:
- Teams机器人没法并发接收消息是正常的吗?
- 如果不正常的话,有没有人遇到过类似问题,该怎么解决?
我的解答
这种情况肯定不正常,Teams本身是支持并发推送消息到机器人的,我之前帮好几个开发者排查过类似的情况,给你几个具体的排查和解决方向:
先查aiohttp服务的阻塞点:虽然aiohttp是异步框架,但如果你的消息处理逻辑里藏着同步阻塞操作(比如用了requests这类同步HTTP库,或者有大量CPU密集型计算),会直接把整个事件循环卡死,后面的请求只能排队等待。解决办法要么把所有阻塞操作改成异步实现(比如用aiohttp的异步请求代替requests),要么用
asyncio.to_thread()把同步代码包装成异步任务,让它不阻塞主事件循环。检查Azure Bot的会话锁定机制:Azure Bot Service默认有个「会话锁定」的功能,是为了防止同一个会话内的消息乱序,但不同用户/不同会话的消息是完全可以并发的。你可以先确认自己的代码里有没有手动加全局锁,再去Azure Bot的配置里看看有没有误开了全局级别的锁定(免费版默认不会,但保险起见查一下)。如果是同一个会话内需要并发处理消息,可能需要调整Bot Framework的会话锁定策略,但跨会话的并发肯定是默认支持的。
调整aiohttp的服务配置:如果aiohttp的默认连接数、队列长度设置得太小,可能会导致Teams的推送请求被临时排队。启动服务的时候可以调大
backlog参数,或者用多进程模式运行aiohttp,比如:
import asyncio from aiohttp import web async def main(): app = web.Application() # 注册你的路由... runner = web.AppRunner(app) await runner.setup() # 调大backlog参数,支持更多待处理连接 site = web.TCPSite(runner, '0.0.0.0', 8080, backlog=100) await site.start() await asyncio.Event().wait() if __name__ == '__main__': asyncio.run(main())
- 加日志确认消息推送时机:你可以在aiohttp的消息接收入口加个详细日志,记录每个请求的会话ID、用户ID和接收时间,看看是Teams根本没把你的消息推过来,还是你的服务没及时处理。比如:
async def teams_webhook_handler(request): payload = await request.json() conv_id = payload.get('conversation', {}).get('id') user_id = payload.get('from', {}).get('id') print(f"[Received] User {user_id} in Conv {conv_id} at {payload.get('timestamp')}") # 后续处理逻辑 return web.Response(status=200)
另外你提到直接调用API没问题,说明你的异步服务本身是支持并发的,问题大概率出在Teams与Bot Service的交互环节,或者你的消息处理逻辑里有阻塞点。建议先从加日志排查消息是否被Teams推送入手,再逐步定位阻塞点。
备注:内容来源于stack exchange,提问作者Uncle Jesse

