Django 是用一个线程处理 WSGI 还是 Gunicorn 中的多个请求?
Does Django use one thread to process several requests in WSGI or Gunicorn?
如题,我想知道当运行通过WSGI或Gunicorn时,Django是否使用一个线程来处理多个请求?
我知道从不应该访问的地方访问请求是一种不好的做法,但我仍然想这样做。 (我认为有充分的理由,例如在我的自定义模板加载器中访问当前用户和站点。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
我的question/concern是:能保证requests/users在生产中不混吗?例如,我担心第二个用户被识别为第一个用户,因为该线程正在用于我的多个请求。或者,请求在原始请求尚未完成时被另一个请求覆盖。这可能吗,或者每个请求在 WSGI 和 Gunicorn 中都有自己的本地线程?
理论上,Django使用异步实例来处理不同的请求。即当一个客户端的请求来到I/O操作时,它会发送I/O请求(即在数据库中查找),然后存储当前状态并让另一个客户端处理它的请求。因此,您不必担心“线程安全”或“线程数据安全”问题。因为在 Django 中总是有一个主线程负责生产线程。
要检查 Django 是否真的同时运行多个线程,请在您的 Linux 机器上安装并使用 htop
。
It is safe 将 threading.local
与 阻塞函数一起使用 (这就是他们毕竟调用阻塞的原因),但最好使用 contextvars
来隔离还有合作任务。
据我所知,Django不依赖多线程。
每个 WSGI 或 Gunicorn runner-thread 只运行一个只处理一个请求的 Django 实例。
您可以使用 htop
或更好地使用 lsof
检查
这里将 Gunicorn 视为 Web 服务器。它有主进程和工人进程。 Master进程选择空闲的worker进程来处理http请求。有 3 种类型的工人:
- 同步(同步)
- 与线程同步(worker 为 运行ning 个线程共享内存)
- 异步(异步)
没有线程的每个 sync worker 一次处理单个请求,考虑到我们有 2 个请求,它们将由 2 个不同的 worker 处理(分开并彼此隔离 python processes) 或同一个worker,但如果它有一个以上的线程,则由一个worker顺序或并行
运行 一个没有线程的同步工作者的应用程序 运行 它如下:
gunicorn --workers=3 main:app
运行 具有同步工作者和线程的应用程序:
gunicorn --workers=3 --threads=2 --worker-class=gthread main:app
在上面的示例中,每个工作人员一次可以处理 2 个请求。
使用异步 worker,我们将有请求并发:每个 worker(python 进程)将一次处理许多请求,但由一个进程处理。要 运行 gunicorn 和异步 worker 你应该正确设置 worker class:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
可以完全保证,如果您选择没有线程的同步工作者,请求不会混合,而且看起来异步也是如此,对于有线程的同步工作者,您应该实现线程同步,其中多个线程可以同时写入。
看看 django-simple-history 是如何工作的(也许这个库可以满足你的需求)。您可以使用:
try:
from asgiref.local import Local as LocalContext
except ImportError:
from threading import local as LocalContext
然后变量LocalContext()
是线程安全的。
Here就是一个例子。
如题,我想知道当运行通过WSGI或Gunicorn时,Django是否使用一个线程来处理多个请求?
我知道从不应该访问的地方访问请求是一种不好的做法,但我仍然想这样做。 (我认为有充分的理由,例如在我的自定义模板加载器中访问当前用户和站点。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
我的question/concern是:能保证requests/users在生产中不混吗?例如,我担心第二个用户被识别为第一个用户,因为该线程正在用于我的多个请求。或者,请求在原始请求尚未完成时被另一个请求覆盖。这可能吗,或者每个请求在 WSGI 和 Gunicorn 中都有自己的本地线程?
理论上,Django使用异步实例来处理不同的请求。即当一个客户端的请求来到I/O操作时,它会发送I/O请求(即在数据库中查找),然后存储当前状态并让另一个客户端处理它的请求。因此,您不必担心“线程安全”或“线程数据安全”问题。因为在 Django 中总是有一个主线程负责生产线程。
要检查 Django 是否真的同时运行多个线程,请在您的 Linux 机器上安装并使用 htop
。
It is safe 将 threading.local
与 阻塞函数一起使用 (这就是他们毕竟调用阻塞的原因),但最好使用 contextvars
来隔离还有合作任务。
据我所知,Django不依赖多线程。
每个 WSGI 或 Gunicorn runner-thread 只运行一个只处理一个请求的 Django 实例。
您可以使用 htop
或更好地使用 lsof
这里将 Gunicorn 视为 Web 服务器。它有主进程和工人进程。 Master进程选择空闲的worker进程来处理http请求。有 3 种类型的工人:
- 同步(同步)
- 与线程同步(worker 为 运行ning 个线程共享内存)
- 异步(异步)
没有线程的每个 sync worker 一次处理单个请求,考虑到我们有 2 个请求,它们将由 2 个不同的 worker 处理(分开并彼此隔离 python processes) 或同一个worker,但如果它有一个以上的线程,则由一个worker顺序或并行 运行 一个没有线程的同步工作者的应用程序 运行 它如下:
gunicorn --workers=3 main:app
运行 具有同步工作者和线程的应用程序:
gunicorn --workers=3 --threads=2 --worker-class=gthread main:app
在上面的示例中,每个工作人员一次可以处理 2 个请求。
使用异步 worker,我们将有请求并发:每个 worker(python 进程)将一次处理许多请求,但由一个进程处理。要 运行 gunicorn 和异步 worker 你应该正确设置 worker class:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
可以完全保证,如果您选择没有线程的同步工作者,请求不会混合,而且看起来异步也是如此,对于有线程的同步工作者,您应该实现线程同步,其中多个线程可以同时写入。
看看 django-simple-history 是如何工作的(也许这个库可以满足你的需求)。您可以使用:
try:
from asgiref.local import Local as LocalContext
except ImportError:
from threading import local as LocalContext
然后变量LocalContext()
是线程安全的。
Here就是一个例子。