Django是否使用一个线程处理WSGI或Gunicorn中的多个请求?
根据标题,我想知道 Django 在通过 WSGI 或 Gunicorn 运行时是否使用一个线程来处理多个请求?
我知道从不打算访问的地方访问请求是一种不好的做法,但我仍然想这样做。(我认为有充分的理由,例如在我的自定义模板加载器中访问当前用户和站点。Django 模板加载器不提供这两个实体。)
现在我设法使用以下代码从任何地方访问用户等:
import threading
_thread_locals = threading.local()
def get_current_request():
return getattr(_thread_locals, "request", None)
class RequestThreadMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
_thread_locals.request = request
response = self.get_response(request)
return response
我的问题/担忧是:是否保证请求/用户不会在生产中混淆?例如,我担心第二个用户被识别为第一个用户,因为该线程用于我的多个请求。或者,该请求在原始请求尚未完成时被另一个请求覆盖。这是可能的,还是每个请求在 WSGI 和 Gunicorn 中都有自己的本地线程?
回答
在这里将 Gunicorn 视为 Web 服务器。它有主进程和工作进程。主进程选择空闲的工作进程来处理 http 请求。有3种类型的工人:
- 同步(同步)
- 与线程同步(worker 共享内存以运行线程)
- 异步(异步)
每个没有线程的同步工作者一次处理一个请求,考虑到我们有 2 个请求,它们要么由 2 个不同的工作者处理(独立并相互隔离的 Python 进程),要么由同一个工作者处理,但如果它有,则由一个工作者顺序或并行处理多于一个线程要运行一个没有线程的同步工作者的应用程序,请按如下方式运行它:
gunicorn --workers=3 main:app
要使用同步工作线程和线程运行应用程序:
gunicorn --workers=3 --threads=2 --worker-class=gthread main:app
在上面的示例中,每个工作人员一次可以处理 2 个请求。
使用异步工作器,我们将拥有请求并发性:每个工作器(python 进程)将一次处理多个请求,但由一个进程处理。要使用异步工作人员运行 gunicorn,您应该正确设置工作人员类:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
如果您选择没有线程的同步工作线程,则可以完全确定请求不会混合,并且似乎也是异步的,对于有线程的同步工作线程,您应该实现多个线程可以同时写入的线程同步。