用于 Django 的 Gunicorn 异步和线程工作者
Gunicorn async and threaded workers for django
异步
对于 input/output(IO) 绑定,我们需要使用异步代码,默认情况下 django 不是异步的,但我们可以通过 gevent运行ning gunicorn worker 和 monkey patching:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
Gunicorn 2014 年更新日志https://docs.gunicorn.org/en/stable/2014-news.html?highlight=monkey#gevent-worker:
fix: monkey patching is now done in the worker
- 我是否仍然需要对我的应用程序进行猴子修补,或者它是由工作人员默认完成的?
- gevent 是如何为我的 django 代码实现异步功能的?
线程
如果我们有一个 CPU 绑定,我们需要使用一个 gthread worker with threads:
gunicorn --workers=5 --threads=2 --worker-class=gthread main:app
- 如果我们将此配置用于 i/o 绑定,是否有效?当一个线程因为 i/o 而等待时,另一个线程是否可以工作?
- 由于 i/o 中的等待时间,我明白了 (3) 中的要点(如果我是对的),但如果这是 CPU 界限,那么在我们的例子中将如何第二个线程对我们有帮助,还是仅在内核未被一个线程完全加载并且另一个线程有空间 运行 时才会有帮助?
- (3) 和 (4) 是因为 GIL 没用了吗?
例如,4 个人用 1 个工作线程和 4 个线程向服务器发送请求。 GIL 确保只有 1 个线程工作。第一个人开始处理线程 1,其他 3 个正在等待?那么线程是做什么用的?
我还需要猴子修补我的应用程序还是默认由工作人员完成?
无需修补代码中的任何内容。根本不需要修改代码。
gevent 是如何为我的 django 代码实现异步功能的?
gunicorn
修补一切。
如果我们将此配置用于i/o绑定,是否有效?当一个线程因为 i/o 而等待时,另一个线程是否可以工作?
此配置适用于 i/o 绑定。线程可以随时在它们之间切换(切换最终由操作系统控制),无论当前线程是否正在执行 I/O 或 CPU 绑定计算。多线程可以在多线程CPUs上同时工作。相比之下,greenlets更多的是协程而不是线程。如果协程被 I/O 阻塞,它会主动允许另一个协程控制 CPU 并执行非 I/O 的事情。
由于 i/o 中的等待时间,我看到了 (3) 中的要点(如果我是对的),但如果这是 CPU 界限,如何在我们的例子中,第二个线程会帮助我们还是仅在内核未被一个线程完全加载并且另一个线程有空间 运行?
时才会有帮助
对于单线程 CPU 上的纯 CPU 有界任务,额外的线程毫无意义。
(3)和(4)是因为GIL没用了吗?
GIL 禁止您的 Python 代码同时 运行ning,但 gunicorn 主要使用其未用 Python 编写的库。你不能 运行 你的 Django 代码(在 Python 中)有多个线程,但是 I/O 任务(由 gunicorn 处理,而不是在 Python 中)可以同时进行。如果确实需要 CPU 利用率,请使用多个进程 (workers=2 * CPU_THREADS + 1
) 而不是多个 gthread,或者考虑非 CPython 解释器,例如 pypy
,它不受 GIL 的约束,但可能与您的代码不兼容。
异步
对于 input/output(IO) 绑定,我们需要使用异步代码,默认情况下 django 不是异步的,但我们可以通过 gevent运行ning gunicorn worker 和 monkey patching:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
Gunicorn 2014 年更新日志https://docs.gunicorn.org/en/stable/2014-news.html?highlight=monkey#gevent-worker:
fix: monkey patching is now done in the worker
- 我是否仍然需要对我的应用程序进行猴子修补,或者它是由工作人员默认完成的?
- gevent 是如何为我的 django 代码实现异步功能的?
线程
如果我们有一个 CPU 绑定,我们需要使用一个 gthread worker with threads:
gunicorn --workers=5 --threads=2 --worker-class=gthread main:app
- 如果我们将此配置用于 i/o 绑定,是否有效?当一个线程因为 i/o 而等待时,另一个线程是否可以工作?
- 由于 i/o 中的等待时间,我明白了 (3) 中的要点(如果我是对的),但如果这是 CPU 界限,那么在我们的例子中将如何第二个线程对我们有帮助,还是仅在内核未被一个线程完全加载并且另一个线程有空间 运行 时才会有帮助?
- (3) 和 (4) 是因为 GIL 没用了吗?
例如,4 个人用 1 个工作线程和 4 个线程向服务器发送请求。 GIL 确保只有 1 个线程工作。第一个人开始处理线程 1,其他 3 个正在等待?那么线程是做什么用的?
我还需要猴子修补我的应用程序还是默认由工作人员完成?
无需修补代码中的任何内容。根本不需要修改代码。gevent 是如何为我的 django 代码实现异步功能的?
gunicorn
修补一切。如果我们将此配置用于i/o绑定,是否有效?当一个线程因为 i/o 而等待时,另一个线程是否可以工作?
此配置适用于 i/o 绑定。线程可以随时在它们之间切换(切换最终由操作系统控制),无论当前线程是否正在执行 I/O 或 CPU 绑定计算。多线程可以在多线程CPUs上同时工作。相比之下,greenlets更多的是协程而不是线程。如果协程被 I/O 阻塞,它会主动允许另一个协程控制 CPU 并执行非 I/O 的事情。由于 i/o 中的等待时间,我看到了 (3) 中的要点(如果我是对的),但如果这是 CPU 界限,如何在我们的例子中,第二个线程会帮助我们还是仅在内核未被一个线程完全加载并且另一个线程有空间 运行?
时才会有帮助 对于单线程 CPU 上的纯 CPU 有界任务,额外的线程毫无意义。(3)和(4)是因为GIL没用了吗?
GIL 禁止您的 Python 代码同时 运行ning,但 gunicorn 主要使用其未用 Python 编写的库。你不能 运行 你的 Django 代码(在 Python 中)有多个线程,但是 I/O 任务(由 gunicorn 处理,而不是在 Python 中)可以同时进行。如果确实需要 CPU 利用率,请使用多个进程 (workers=2 * CPU_THREADS + 1
) 而不是多个 gthread,或者考虑非 CPython 解释器,例如pypy
,它不受 GIL 的约束,但可能与您的代码不兼容。