Waitress 如何处理并发任务?

How does Waitress handle concurrent tasks?

我正在尝试使用 Django 和 Waitress 构建一个 python 网络服务器,但我想知道 Waitress 如何处理并发请求,以及何时 阻塞 可能发生。


虽然 Waitress documentation 提到多个工作线程可用,但它没有提供很多关于它们是如何实现的以及 python GIL 如何影响它们的信息(强调我自己的) :

When a channel determines the client has sent at least one full valid HTTP request, it schedules a "task" with a "thread dispatcher". The thread dispatcher maintains a fixed pool of worker threads available to do client work (by default, 4 threads). If a worker thread is available when a task is scheduled, the worker thread runs the task. The task has access to the channel, and can write back to the channel's output buffer. When all worker threads are in use, scheduled tasks will wait in a queue for a worker thread to become available.

关于Whosebug 的信息似乎也不多。从问题 "Is Gunicorn's gthread async worker analogous to Waitress?":

Waitress has a master async thread that buffers requests, and enqueues each request to one of its sync worker threads when the request I/O is finished.


这些陈述没有涉及 GIL(至少根据我的理解),如果有人可以详细说明工作线程如何为 Waitress 工作,那就太好了。谢谢!

以下是事件驱动异步服务器的一般工作方式:

  • 启动一个进程并监听传入的请求。利用操作系统的事件通知 API 可以很容易地从单个 thread/process.
  • 为数千个客户端提供服务
  • 由于只有一个进程管理所有连接,您不希望在此进程中执行任何缓慢(或阻塞)的任务。因为那样它会阻止每个客户端的程序。
  • 为了执行阻塞任务,服务器将任务委托给 "workers"。 Worker 可以是线程(运行在同一进程中)或单独的进程(或子进程)。现在主进程可以继续为客户端提供服务,而工作人员执行阻塞任务。

How does Waitress handle concurrent tasks?

与我刚才描述的方式几乎相同。对于工人,它创建线程,而不是进程。

how the python GIL affects them

女服务员为工人使用线程。所以,是的,它们受到 GIL 的影响,因为它们并不是真正的并发,尽管它们看起来是。 "Asynchronous" 是正确的术语。

Python 运行 中的线程在单个进程中,在单个 CPU 核心上,并且不要 运行 并行。一个线程在非常短的时间内获取 GIL 并执行其代码,然后另一个线程获取 GIL。

但是由于 GIL 是在网络上发布的 I/O,每当有网络事件(例如传入请求)时,父进程将始终获取 GIL,这样您就可以放心 GIL 将不影响网络绑定操作(如接收请求或发送响应)。

另一方面,Python 进程实际上是并发的:它们可以 运行 在多个内核上并行。但是 Waitress 不使用流程。

你应该担心吗?

如果您只是在执行像数据库 read/writes 这样的小阻塞任务并且每秒只服务几百个用户,那么使用线程并不是那么糟糕。

为了服务大量用户或执行长时间的 运行ning 阻塞任务,您可以考虑使用外部任务队列,例如 Celery。这比自己生成和管理进程要好得多。