使用 uvicorn 在同一线程中运行多个 asgi 应用程序

Dev*_*wal 6 python python-asyncio asgi uvicorn

我想在同一个线程中运行 starlette 和 django 应用程序。

(将它们放在同一线程中可以实现它们之间的快速线程本地通信)。

考虑到 asgi 应用程序只是协程,我认为这在理论上应该是可能的asyncio.gather()


我想出了一个小窍门来完成这项工作,但它有一些局限性。

from uvicorn import Server, Config

configs = [Config(app1, uds='app1.sock'), Config(app2, uds='app2.sock')]
coros = [Server(c).serve() for c in configs]

await asyncio.gather(*coros)
Run Code Online (Sandbox Code Playgroud)
  1. 不支持reloadworkers选项。
  2. Ctrl+C 仅适用于一个应用程序。
INFO:     Started server process [86066]
INFO:     Waiting for application startup.
INFO:     Started server process [86066]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     Uvicorn running on unix socket app1.sock (Press CTRL+C to quit)
INFO:     Application startup complete.
INFO:     Uvicorn running on unix socket app2.sock (Press CTRL+C to quit)
^CINFO:     Shutting down
INFO:     Finished server process [86066]
^C^C^C^C^C
Run Code Online (Sandbox Code Playgroud)

有什么更好的方法来做到这一点?

Dev*_*wal 8

更新 - 如果两个应用程序之间的路径分离,您可以使用它来跳过 starlette 的中间件:

from mydjangoapp.asgi import application as django_app

ws_app = Starlette(...)

async def app(scope, receive, send):
    path = scope.get("path")
    chosen = ws_app
    if not (path is None or path.startswith("/ws")):
        chosen = django_app
    return await chosen(scope, receive, send)
Run Code Online (Sandbox Code Playgroud)

傻我啊!Starlette 支持安装任意 ASGI 应用程序,这意味着您只需执行以下操作即可从命令行使用任何 ol' ASGI 服务器。

from mydjangoapp.asgi import application as django_app

app = Starlette(...)

app.mount('/', django_app)
Run Code Online (Sandbox Code Playgroud)