3

我想在同一个线程中运行一个 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)

  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

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

4

1 回答 1

4

更新 - 如果您有 2 个应用程序之间的路径分离,您可以使用它来跳过 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)

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

from mydjangoapp.asgi import application as django_app

app = Starlette(...)

app.mount('/', django_app)
于 2020-02-12T10:24:35.220 回答