协程里调用了一个阻塞函数会怎样?Flask 放到 ASGI 服务器上,sync 视图会不会拖慢整个服务?这篇用真实的 uvicorn、gunicorn 与两个 WSGI 到 ASGI 的适配器,把阻塞的影响范围量出来(还有一个我没预料到的串行结果)。
在协程里调用 time.sleep(2)(阻塞) 另一个请求用了 1620 ms await asyncio.sleep(2)(让出) 另一个请求用了 2 ms await asyncio.to_thread(time.sleep, 2)(放到线程) 另一个请求用了 3 ms
上一篇:Async View 的执行边界;下一篇:Flask 与 ASGI。
async 视图里 time.sleep(2) 另一个请求(/fast)用了 5 ms async 视图里 await asyncio.sleep(2) 另一个请求(/fast)用了 4 ms sync 视图里 time.sleep(2) 另一个请求(/fast)用了 3 ms
async 视图里 time.sleep(2) 另一个请求(/fast)用了 1609 ms async 视图里 await asyncio.sleep(2) 另一个请求(/fast)用了 1599 ms sync 视图里 time.sleep(2) 另一个请求(/fast)用了 1608 ms
这是本篇最出乎意料的结果:我原以为 sync 视图会被放进线程池并发执行,实测却是串行,所以去看了 asgiref 的源码确认原因。
async 视图里 time.sleep(2) 另一个请求(/fast)用了 2 ms async 视图里 await asyncio.sleep(2) 另一个请求(/fast)用了 1 ms sync 视图里 time.sleep(2) 另一个请求(/fast)用了 4 ms
["Executing <Task finished name='Task-1' coro=<main() done, defined at <string>:4> result=None created at <stdlib>/asyncio/runners.py:110> took 0.510 seconds"]