商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 为什么Python异步编程中阻塞函数会引发整个服务的延迟?

为什么Python异步编程中阻塞函数会引发整个服务的延迟?

  发布于2026-07-14 阅读(0)

扫一扫,手机访问

为什么 Python 异步编程里,一个简单的阻塞函数就能让整个服务“瘫痪”?答案其实很直接:因为 asyncio 的事件循环是单线程的,它没有分身术。一旦某个协程里跑了一个同步阻塞操作,整条流水线就会卡死,所有协程都得干等着。

asyncio 事件循环根本不能并行执行 CPU 或同步 I/O

事件循环的工作方式就是轮询加回调,调度协程切换,但从来不创建新线程。这意味着,一旦你在 async 函数里放了个 time.sleep()requests.get()open().read(),或者任何没有适配异步的库,控制权就彻底交出去了——没有回调、没有切换、没有“让出”,直到那个阻塞调用返回为止。

  • time.sleep(2) 会让整个服务暂停 2 秒,哪怕你同时跑了 100 个协程
  • requests.get("https://api.example.com") 在等待响应时,事件循环完全无法处理其他任务
  • 同步数据库驱动(如 sqlite3.connect())打开连接或执行查询,同样冻结调度

常见误用:以为加了 async/await 就自动异步了

这其实只是语法糖,不改变底层行为。比如下面这段代码,看起来是异步函数,但依然会阻塞:

async def bad_fetch():
    import requests
    return requests.get("https://httpbin.org/delay/3").json()  # ❌ 同步阻塞

它被标记为 async,但内部调用的是纯同步函数。事件循环照常启动这个协程,然后卡在 requests.get 上,动弹不得。

  • 真正异步的替代方案:用 aiohttphttpx.AsyncClientaiomysqlaiofiles
  • 没现成异步库?必须显式移交到线程池:await loop.run_in_executor(None, sync_func, *args)
  • 别把 async def 当装饰器——它不魔法转化同步代码

阻塞导致的连锁反应:超时失效、任务堆积、资源泄漏

一个协程阻塞,不仅自己卡住,还会拖垮所有依赖它的逻辑:

  • asyncio.wait_for(task(), timeout=1) 对阻塞调用无效——超时异常可能根本抛不出,因为事件循环没机会检查是否超时
  • asyncio.gather() 并发多个任务?只要其中一个是同步阻塞,其他任务全得陪等
  • 数据库连接未关闭、文件句柄未释放,往往是因为阻塞导致 async with__aexit__ 根本没执行到

真正难察觉的点不是“哪里写了阻塞”,而是“哪里漏掉了异步适配”。比如日志写入用了 logging.info()(同步),配置加载用了 json.load(open(...))(同步),甚至第三方 SDK 内部偷偷调了 subprocess.run()(同步)。这些地方不会报错,但会在高并发下突然集体变慢。

本文转载于:https://www.php.cn/faq/2819747.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注