为什么Django Channels Daphne不能使用多线程并发处理请求?

Why can't Django Channels Daphne use multi-threading to process request concurrently?

我知道 Python 的 GIL 并且 Python 中的线程并不像在 Go 中生成一个 go 例程那么容易。但是,在我看来 Ruby 能够通过 Puma 和 Unicorn 实现多线程并发。我的问题实际上有两个方面。我的经验仅限于 Django Channel 的 Daphne。

  1. 除了Daphne,还有什么像Rails中的puma和unicorn一样多线程的web服务器选择?

  2. 从 Daphne 的文档中,我了解到并行是通过生成新进程(worker)来实现的

    Because the work of running consumers is decoupled from the work of talking to HTTP, WebSocket and other client connections, you need to run a cluster of “worker servers” to do all the processing. Each server is single-threaded, so it’s recommended you run around one or two per core on each machine; it’s safe to run as many concurrent workers on the same machine as you like, as they don’t open any ports (all they do is talk to the channel backend).

如前所述,每个 worker 都是单线程的。当涉及到 I/O 函数调用时,worker 被完全阻塞。我的问题是,为什么 Daphne 不能为每个请求生成多个线程。当一个线程被 I/O 阻塞时,例如数据库访问,CPU 切换到执行另一个线程,直到前面的线程被解除阻塞。同样,Node.js 是单线程的,但它通过非阻塞 I/O 确实很好地实现并发。为什么同样的壮举很难实现。在 Python? (除了它缺乏良好的事件循环这一事实。)

目前,uvicorn 是达芙妮的唯一替代品,它支持多处理并已准备好用于生产。

$ pip install uvicorn

$ uvicorn avilpage.asgi --workers 4

这将启动具有 4 个工人的服务器。

因为daphne/uvicorn使用asyncio做多任务,我猜多线程没有意义。

workers 不是单线程的。它们中的每一个都会打开一个线程池来 运行 所有数据库查询以及您 运行 sync_to_async 上的任何内容。 Daphne 的重点是异步,你在主线程中使用 asyncio 的时间越长,它运行的速度就越快。您希望尽可能地消除上下文切换,以便 CPU 缓存保持最新。另外,Python 的 GIL 一次只保持一个线程工作,这就是为什么多线程没有速度提升的原因。你可以有 25 个线程,它 运行 和 1 个线程一样快:https://gist.github.com/agronick/692d9a7bc41b75449f8f5f7cad93a924