Django的Gunicorn异步和线程工作原理

4

异步

对于输入/输出(IO)受限的情况,我们需要使用异步代码,而django默认情况下不是异步的,但是我们可以通过使用带有gevent工作进程和monkey patching的gunicorn来实现:

gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app

2014年的Gunicorn变更日志https://docs.gunicorn.org/en/stable/2014-news.html?highlight=monkey#gevent-worker:

修复:现在在worker中进行猴子补丁。

  1. 我是否仍需要为我的应用程序打猴子补丁,或者它默认由worker完成?
  2. gevent如何为我的Django代码实现异步功能?

线程

如果我们有一个CPU密集型任务,则需要使用带有线程的gthread worker:

gunicorn --workers=5 --threads=2 --worker-class=gthread main:app
  1. 如果我们将此配置用于I/O绑定,它会起作用吗?当一个线程因为I/O而等待时,另一个线程能够工作吗?
  2. 我看到了(3)中的观点(如果我没错),因为I/O等待时间的原因,但如果这是一个CPU绑定,那么在我们的情况下第二个线程如何帮助我们,或者只有当一个线程没有完全负载核心并且有空余的运行空间时才有帮助?
  3. 由于GIL,(3)和(4)是无用的吗?例如,有4个人向服务器发送请求,使用1个工作进程和4个线程。 GIL确保只有1个线程在工作。第一个人使用线程1开始处理,其他3个人在等待?那么线程是用来做什么的呢?
1个回答

7
  1. 我是否需要对我的应用程序进行猴子补丁或者这是工作线程默认完成的?
    无需在代码中打补丁,也不需要修改代码。

  2. gevent如何实现我的Django代码的异步功能?
    gunicorn会打补丁。

  3. 如果我们针对I/O限制使用此配置,它是否有效?当一个线程由于I/O而处于等待状态时,另一个线程是否能够工作?
    这种配置适用于I/O限制。线程可以随时切换(切换由操作系统控制),无论当前线程是在执行I/O还是CPU密集型计算。多个线程可以同时在多线程CPU上工作。相比之下,greenlet更像协程而不是线程。如果协程因I/O而被阻塞,它会主动允许另一个协程控制CPU并执行非I/O任务。

  4. 我理解(3)的观点(如果我没错)是因为I/O的等待时间,但如果这是一个CPU密集型任务,在我们的情况下第二个线程如何帮助我们?或者只有当核心没有被一个线程完全占满,并且有空间运行另一个线程时它才有用?
    对于单线程CPU上的纯CPU绑定任务,额外的线程意义不大。

  5. (3)和(4)由于GIL是无用的吗?
    GIL禁止Python代码同时运行,但是gunicorn大多使用非Python编写的库。您无法使用多个线程运行您的Django代码(在Python中),但是I/O任务(由gunicorn处理,而不是在Python中)可以并发进行。如果确实需要CPU利用率,请使用多个进程(workers=2 * CPU_THREADS + 1)替代多个gthreads,或考虑非CPython解释器,如pypy,它不受GIL的限制,但可能与您的代码不兼容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接