asyncio 服务跑久了内存上涨、任务数只增不减,多半是任务泄漏,定位时先分清是任务没回收,还是事件循环被阻塞。
一、先看现象:用 asyncio.all_tasks 定期统计任务数量和名称,看增长来自哪类任务;同时留意 Task was destroyed but it is pending 之类的告警,它往往指向创建后未被持有的任务。
二、最常见的根因是任务引用丢失:create_task 返回的任务没有保存引用,任务还没跑完就被回收,异常也无人处理。做法是把任务放进一个集合管理,任务完成时用回调移除,别让它裸奔。
三、查取消逻辑:长轮询、重试循环如果没有超时和取消分支,任务会一直挂着。给每个长任务加超时,关闭时显式取消并 await 它,确认取消真的生效。
四、查事件循环阻塞:同步 IO、重计算、没加 await 的阻塞调用会占住事件循环,任务排队看起来像泄漏。用 run_in_executor 把阻塞调用隔离出去,再对比任务堆积是否缓解。
五、结构化并发更省心:能用 TaskGroup 的场景尽量用它,子任务异常、取消都有明确归属,比到处 create_task 好排查得多。
你们线上 asyncio 任务泄漏最常见的是哪一种:引用丢失、取消缺失,还是事件循环被阻塞?