讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 Python/FastAPI 中监控事件循环中的待处理异步任务?

星涛姑娘_1296

星涛姑娘_1296

发布时间:2026-04-11 11:41:27

|

596人浏览过

|

来源于php中文网

原创

如何在 Python/FastAPI 中监控事件循环中的待处理异步任务?

本文详解如何使用 asyncio.all_tasks() 实时获取并分析当前事件循环中所有未完成的异步任务,帮助定位 fastapi 应用性能瓶颈、任务积压或长时阻塞问题。

本文详解如何使用 asyncio.all_tasks() 实时获取并分析当前事件循环中所有未完成的异步任务,帮助定位 fastapi 应用性能瓶颈、任务积压或长时阻塞问题。

在基于 asyncio 的 Python Web 应用(如 FastAPI)中,事件循环是异步调度的核心。当请求量激增、I/O 延迟升高或协程中存在隐式同步阻塞(如未 await 的 CPU 密集操作、误用同步库)时,任务可能持续堆积在事件循环中,导致响应延迟、内存增长甚至服务不可用。此时,监控“待处理任务”(pending tasks)的数量与状态,是诊断性能问题的关键切入点。

✅ 正确获取所有待处理任务:asyncio.all_tasks()

Python 标准库提供了权威且轻量的方式——asyncio.all_tasks(loop=None),它返回一个包含所有尚未完成(not yet done)的 Task 对象的 set,涵盖:

  • 已调度但尚未开始执行的任务(pending);
  • 正在运行但被 await 暂停的任务(running/suspended);
  • 当前正在执行 all_tasks() 的任务本身(即调用者所在 Task);
  • 入口任务(如 asyncio.run() 包裹的主协程任务)。
import asyncio
import logging

# 在任意异步上下文中调用(例如 FastAPI 路由、中间件或健康检查端点)
async def get_pending_task_summary():
    tasks = asyncio.all_tasks()  # 获取当前运行 Loop 中所有未完成 Task
    pending_count = len(tasks)
    logging.info(f"当前事件循环中待处理任务总数: {pending_count}")

    # 可选:按状态分类统计
    running = [t for t in tasks if not t.done() and not t.cancelled()]
    pending = [t for t in tasks if t._state == "PENDING"]  # 注意:_state 是内部属性,仅作调试参考
    logging.debug(f"Running tasks: {len(running)}, Pending (internal): {len(pending)}")

    return {"total": pending_count, "running": len(running)}

⚠️ 注意:asyncio.all_tasks() 不区分“宏任务/微任务”(这是浏览器 JS 事件循环概念),而是面向 asyncio.Task 的统一视图——所有通过 asyncio.create_task()、asyncio.ensure_future() 或 await 自动调度的协程,最终都会表现为 Task 实例。

? 深度诊断:日志化与栈追踪

单纯计数不够?可进一步打印任务详情或完整调用栈,快速识别“卡住”的协程:

立即学习“Python免费学习笔记(深入)”;

macOS UI 自动化技能包 —— 用 Python 控制你的 Mac
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac

让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限

下载
from fastapi import APIRouter
import asyncio
import traceback

router = APIRouter()

@router.get("/debug/tasks")
async def debug_tasks():
    tasks = asyncio.all_tasks()

    # 1. 日志化每个任务基本信息
    task_logs = []
    for task in tasks:
        task_info = {
            "name": task.get_name(),
            "done": task.done(),
            "cancelled": task.cancelled(),
            "exception": str(task.exception()) if task.done() and task.exception() else None,
        }
        task_logs.append(task_info)

    # 2. (可选)对运行中任务打印栈帧(谨慎使用,避免阻塞)
    for task in tasks:
        if not task.done() and not task.cancelled():
            # 使用 print_stack() 输出到 stderr,适合调试环境
            task.print_stack(limit=5)  # 仅显示最近 5 层调用

    return {"tasks": task_logs, "count": len(tasks)}

响应示例:

{
  "tasks": [
    {
      "name": "task-get-user",
      "done": false,
      "cancelled": false,
      "exception": null
    }
  ],
  "count": 42
}

? 提示:在生产环境建议将 print_stack() 替换为结构化日志(如 logging.debug(task.get_coro().__qualname__)),避免 I/O 阻塞或敏感信息泄露。

? 常见误区澄清

你提到:“每次 await 都创建一个待执行任务,慢则积压”。这不准确:

  • await 本身不创建新 Task,它只是暂停当前 Task 并让出控制权;
  • 新 Task 仅在显式调用 create_task()、ensure_future(),或 FastAPI 自动包装路由协程时产生;
  • 真正造成积压的是:
    ▪️ 高并发下未及时 await 的 I/O 操作(如数据库连接池耗尽);
    ▪️ 协程内执行了同步阻塞操作(如 time.sleep()、requests.get());
    ▪️ 错误地将 CPU 密集型任务放入事件循环(应改用 loop.run_in_executor())。

✅ 最佳实践建议

场景 推荐方案
实时监控 在 /health 或 Prometheus 指标端点中定期调用 len(asyncio.all_tasks()),设置告警阈值(如 > 100)
故障排查 结合 task.get_coro().__qualname__ 和 task.get_name() 快速定位异常模块
压力测试 在 Locust/Artillery 测试脚本中注入 debug_tasks() 调用,观察任务增长曲线
自动清理 对超时任务主动 task.cancel()(需配合 asyncio.wait_for() 使用)

掌握 asyncio.all_tasks(),你就拥有了透视 FastAPI 异步心脏的“X光机”——无需第三方依赖,即可精准定位任务积压根源,让高并发下的性能调优从玄学回归工程实践。

热门AI工具

更多
切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

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

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

1831

2023.07.20

python能做什么
python能做什么

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

4964

2023.07.25

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

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

1789

2023.07.31

python教程
python教程

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

29757

2023.08.03

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

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

3547

2023.08.04

python eval
python eval

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

3567

2023.08.04

scratch和python区别
scratch和python区别

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

1223

2023.08.11

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

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

616

2023.08.10

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn