ASGI 下只要有一个中间件不支持 async,Django 就得为它做适配。这篇量一下适配的代价、日志里怎么看出来,以及「sync 中间件会不会毁掉并发」这个常见担心有没有在实验里成立。
没有中间件 0.536 ms 5 个 async 中间件 0.550 ms 1 个只支持 sync 的中间件 0.681 ms 5 个只支持 sync 的中间件 0.685 ms
额外耗时约 0.15 ms,而且第一个 sync 中间件之后几乎不再增加——推测是连续的 sync 中间件共用了同一次线程切换(我没有查源码验证)。这里的请求耗时是 DEBUG=True 时串行测的,数字只用来比较,不是绝对性能。
Asynchronous handler adapted for middleware proj.mw.SyncMW. 没有同步中间件时(async5)日志里 adapted 行数: 0
async 中间件里 await asyncio.sleep(0.2) 20 并发总耗时 413 ms 全部 200: True sync 中间件里 time.sleep(0.2) 20 并发总耗时 420 ms 全部 200: True
在这个测法下不会:20 个并发请求,sync 中间件里 time.sleep(0.2) 与 async 中间件里 await asyncio.sleep(0.2) 总耗时相同。原因是每个请求的同步部分在自己的线程里(第 112 篇)。但线程数不是无限的(第 113 篇量到过线程池上限),并发数远高于 20 时未必仍然成立,本文没有测。