Gunicorn Django 线程
-
20-12-2019 - |
题
我无法找到有关 Gunicorn/Django 进程/线程生命周期的文档。
假设在 process_response() 中间件挂钩期间生成了一个守护线程。AFAIK 这个线程不会阻止 HTTP 响应。但是,它会阻塞产生它的线程吗?在工作进程准备好处理另一个请求之前,Gunicorn 是否会等待该线程完成以将其连接回主线程,还是会分离该线程?
数据收集/tasks.py:
from celery import shared_task
@shared_task(ignore_result=True)
def add_event(event_name, event_body):
...
client.add_event(event_name, event_body)
数据收集/中间件.py:
import threading
from data_collection.tasks import add_event
class DataCollectionMiddleware:
def process_response(self, request, response):
...
thread = threading.Thread(target=add_event.delay, args=("Page_Views", event_body))
thread.setDaemon(True)
thread.start()
更多详情:
我编写了一个自定义中间件类来将一些数据发送到外部队列 (RabbitMQ),稍后由 celery 工作线程异步检索和处理这些数据。我不希望这种在线排队调用阻止客户端的响应,因此我将该函数(add_event.delay())包装在“守护进程”线程中(a la http://www.artfulcode.net/articles/threading-django/)。如果出现网络中断并且重试策略有很长的限制,则该线程可能会运行很长时间。在这种情况下,这些线程会阻塞我的 Gunicorn 工作进程吗?
我读了这个问题,但我不确定我的线程是否干扰了“工人的主循环”:在 Django/Gunicorn 应用程序中拥有持久(非守护进程)线程有危险吗?
解决方案
不。从 Gunicorn 工作主线程生成的线程没有什么特别的。
一旦生成线程,它将并行执行,直到完成或死亡。Gunicorn 不知道这些从工作主线程生成的线程,因此它不会尝试加入它们,因此工作主线程不会等待子线程完成。此外,线程的守护进程也没有影响;守护进程只是意味着该线程不会对进程的“活动性”做出贡献,并且将运行直到进程退出,此时它将被自动终止。
如果您想在重新使用同一工作线程之前等待这些线程完成,则必须在 WSGI 应用程序之前执行此操作(例如 django.core.handlers.wsgi.WSGIHandler.__call__())返回。或者为 Gunicorn 编写一些疯狂的猴子补丁来跟踪子线程。
TL;DR 您绝对可以通过从工作主线程生成长时间运行的子线程来不受限制地增长线程。最好保证他们会在超时的时间内完成。