发布于2026-07-14 阅读(0)
扫一扫,手机访问
为什么 Python 异步编程里,一个简单的阻塞函数就能让整个服务“瘫痪”?答案其实很直接:因为 asyncio 的事件循环是单线程的,它没有分身术。一旦某个协程里跑了一个同步阻塞操作,整条流水线就会卡死,所有协程都得干等着。
事件循环的工作方式就是轮询加回调,调度协程切换,但从来不创建新线程。这意味着,一旦你在 async 函数里放了个 time.sleep()、requests.get()、open().read(),或者任何没有适配异步的库,控制权就彻底交出去了——没有回调、没有切换、没有“让出”,直到那个阻塞调用返回为止。
time.sleep(2) 会让整个服务暂停 2 秒,哪怕你同时跑了 100 个协程requests.get("https://api.example.com") 在等待响应时,事件循环完全无法处理其他任务sqlite3.connect())打开连接或执行查询,同样冻结调度这其实只是语法糖,不改变底层行为。比如下面这段代码,看起来是异步函数,但依然会阻塞:
async def bad_fetch():
import requests
return requests.get("https://httpbin.org/delay/3").json() # ❌ 同步阻塞
它被标记为 async,但内部调用的是纯同步函数。事件循环照常启动这个协程,然后卡在 requests.get 上,动弹不得。
aiohttp、httpx.AsyncClient、aiomysql、aiofilesawait 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()(同步)。这些地方不会报错,但会在高并发下突然集体变慢。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8