WSGI 和 ASGI 两个入口,启动流程有什么不同?同一个视图在两种入口下运行在哪个线程?这篇不启动服务器,直接导入 wsgi.py / asgi.py,并用最小的 WSGI 环境与 ASGI scope 调用 handler。
WSGI:import proj.wsgi 之后 → django.core.handlers.wsgi.WSGIHandler | apps.ready = True | 事件: ['LabConfig.ready()', 'MW.__init__(中间件链在构建 handler 时创建)'] ASGI:import proj.asgi 之后 → django.core.handlers.asgi.ASGIHandler | apps.ready = True | 事件: ['LabConfig.ready()', 'MW.__init__(中间件链在构建 handler 时创建)']
get_wsgi_application() 与 get_asgi_application() 都先 django.setup()(所以 ready() 在导入时就跑完),再创建 handler,handler 的构造函数里构建中间件链。
WSGIHandler.__call__ 签名 : (self, environ, start_response) ASGIHandler.__call__ 签名 : (self, scope, receive, send) 是协程函数: True
WSGI 是同步的可调用对象;ASGI 是协程函数,收发消息都通过 await。
WSGI 同步视图 → ('200 OK', 'thread=MainThread main=True')
WSGI async 视图 → ('200 OK', 'async thread=ThreadPoolExecutor-1_0 main=False')
ASGI 同步视图 → (200, 'thread=ThreadPoolExecutor-2_0 main=False')
ASGI async 视图 → (200, 'async thread=MainThread main=True')这是理解「为什么在 ASGI 下调同步 ORM 会有线程问题」「为什么 WSGI 下的 async 视图没有好处」的关键:Django 在两种入口下都保证视图能运行,但「不匹配」的一方要付线程切换的代价(第 111–116 篇)。
ValueError: Django can only handle ASGI/HTTP connections, not lifespan.
需要 startup / shutdown 钩子时要自己包一层 ASGI 应用(本文没有做)。