如何在 Python/FastAPI 中监控事件循环中所有待执行的异步任务数量

落枫大大_8036

落枫大大_8036

2026-04-11

492人浏览

原创

如何在 Python/FastAPI 中监控事件循环中所有待执行的异步任务数量

本文详解如何使用 asyncio.all_tasks() 获取当前事件循环中所有未完成(pending 或 running)的 task 对象,并通过实际代码演示任务统计、日志记录与堆栈分析,助力 fastapi 应用性能排查。

本文详解如何使用 asyncio.all_tasks() 获取当前事件循环中所有未完成(pending 或 running)的 task 对象,并通过实际代码演示任务统计、日志记录与堆栈分析,助力 fastapi 应用性能排查。

在构建高并发 FastAPI 服务时,异步任务的积压往往是响应延迟或资源耗尽的早期信号。但需明确:await 本身不会自动创建新任务——它只是挂起当前协程,等待被 await 的可等待对象(如 asyncio.sleep()、HTTP 请求、数据库查询)完成;真正生成独立可调度任务的是 asyncio.create_task()、asyncio.ensure_future() 或 FastAPI 内部的 BackgroundTasks 等显式调度行为。因此,“待执行任务数”反映的是已提交至事件循环、尚未完成(.done() 为 False)的所有 Task 实例总数,包括正在运行、已暂停、等待 I/O 或处于队列中的任务。

✅ 获取待执行任务数量(核心方法)

最直接的方式是调用 asyncio.all_tasks(),它返回一个 set,包含当前运行事件循环中所有未完成的 Task 对象:

import asyncio

# 在任意协程内(如 FastAPI 路由处理函数中)
async def monitor_tasks():
    pending_tasks = asyncio.all_tasks()
    count = len(pending_tasks)
    print(f"当前待执行/运行中的任务总数: {count}")
    return count

⚠️ 注意:asyncio.all_tasks() 默认使用 asyncio.get_running_loop() 获取当前事件循环,无需手动传入 loop 参数(除非你显式管理多个 loop,这在标准 FastAPI 场景中极少见)。

Shadows Python Sensei
Shadows Python Sensei

Python 最佳实践助手——代码规范、设计模式、性能优化、测试与类型注解。适用于编写或审查 Python 代码。

下载

? 进阶监控:区分状态与诊断卡顿

仅知总数不够?可进一步过滤活跃任务(非 done)、打印详情或导出堆栈:

import asyncio
import logging

logging.basicConfig(level=logging.DEBUG)

async def diagnose_task_backlog():
    tasks = asyncio.all_tasks()

    # 1. 统计:总任务数 vs 活跃任务数(未完成)
    total = len(tasks)
    active = len([t for t in tasks if not t.done()])
    print(f"[监控] 总任务: {total}, 活跃中: {active}")

    # 2. 日志所有任务基本信息(推荐用于 Prometheus / Grafana 集成)
    for task in tasks:
        logging.debug(
            f"Task {task.get_name() or 'unnamed'} | "
            f"State: {'DONE' if task.done() else 'PENDING'} | "
            f"Coro: {task.get_coro().__qualname__ if task.get_coro() else 'N/A'}"
        )

    # 3. (谨慎使用)打印卡住任务的完整调用栈(定位阻塞点)
    for task in tasks:
        if not task.done() and task._coro.cr_await is None:  # 粗略判断“疑似卡住”
            print(f"\n⚠️  可能卡住的任务 {task.get_name()} 堆栈:")
            task.print_stack(limit=10)

# 在 FastAPI 中作为依赖或中间件调用示例
from fastapi import Depends, APIRouter

router = APIRouter()

@router.get("/health/tasks")
async def get_task_status():
    await diagnose_task_backlog()
    return {"status": "ok"}

? 关键注意事项

  • all_tasks() 包含自身:调用该函数的协程本身也被包装为一个 Task(例如 FastAPI 路由处理函数),因此总数恒 ≥ 1。
  • 不包含普通协程(coroutine):只有被 create_task()、ensure_future() 或框架(如 FastAPI)显式调度的才计入;裸 await coro() 不新增任务。
  • 生命周期敏感:all_tasks() 返回的是瞬时快照。任务可能在你遍历时已完成,建议在关键路径(如请求入口/出口)或定时健康检查中调用。
  • FastAPI 生产环境建议:
    • 避免高频调用(如每个请求都 print_stack),可用 logging.debug + 条件采样;
    • 结合 asyncio.current_task().get_name() 为任务命名,提升可读性:
      task = asyncio.create_task(some_coro(), name="db-query-user-profile")
  • 替代方案(更轻量):若仅需计数,len(asyncio.all_tasks()) 是最低开销方式;避免无谓遍历。

掌握 asyncio.all_tasks() 是异步应用可观测性的基石。它不解决性能瓶颈本身,但为你提供了精准定位“谁在占用事件循环”的第一手证据——当 pending_tasks 持续增长且无法回落时,即可锁定对应协程深入分析 I/O 效率、锁竞争或 CPU 密集型操作,从而真正优化 FastAPI 服务的吞吐与延迟表现。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1571

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

3764

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1589

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

21557

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2667

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2707

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1103

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

576

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2103

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程