How to avoid Django sub thread being killed by uWSGI respawn
我由Django uWSGI创建了一个Web服务器。基本流程是:收到请求后,Django将通过python内置库" Threading"启动子线程以异步编写db,并在主线程中立即将其返回给客户端。
如何,uWSGI有时会重新生成工作进程(也许当进程没有处理请求时?),这导致后台子线程也被杀死,即使尚未完成。有什么线索可以避免uWSGI不重新生成具有正在运行的子线程的工作进程?
uWSGI重生日志:
1 | DAMN ! worker 4 (pid: 31161) died, killed by signal 9 :( trying respawn ... |
uWSGI ini config(版本2.0.12):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [uwsgi] # Django's wsgi file wsgi-file = /home/fh/dj_uwsgi/dj_site/dj_site/wsgi.py master = true processes = 10 http = :8001 threads = 2 enable-threads = true http-timeout = 10 max-requests = 5000 chmod-socket = 664 vacuum = true pidfile = /home/fh/dj_uwsgi/dj_site/uwsgi.pid daemonize = /home/fh/log/uwsgi_dj.log |
Django(1.8版)应用程序伪代码:
在handlers.py中的
:
1 2 3 4 5 6 7 8 9 10 11 | import threading class SubThreadClass(threading.Thread): daemon = True def run(self): # actions to write db def myHandler(): my_sub_thread = SubThreadClass() my_sub_thread.start() |
in views.py:
1 2 3 4 5 | from handlers import myHandler def url_handler(request): myHandler() return HttpResponse() |
在您无法管理的环境中,手动处理线程很少是一个好主意。
您应该使用像Celery这样的脱机工作系统。
在我的情况下,此问题是由于数据库的某些操作延迟所致。
我将uWSGI与Pyramid(http://docs.pylonsproject.org/projects/pyramid/en/latest/)一起使用。由于您使用的是Django(Python),因此很可能该解决方案对您有效。
下面引用的设置位于配置文件production.ini中([uwsgi]节)(http://uwsgi-docs.readthedocs.io/en/latest/Options.html)。
我使用以下规则"解决"了此问题。该规则"解决"了该问题,因为它大大减少了它的发生。到目前为止,我还没有看到可以完全避免的任何东西。我在性能上也有了改进(需要测试,但我们认为是很好的改进)。解决方案基本上是根据数据库允许的连接数来增加线程数(也可以增加数据库允许的连接数)。
规则:
定义流程的数量(production.ini或等效版本中的processs参数)
1 2 3 4 | q=n*2 q - number of processes n - number of CPUs/cores |
确定螺纹的数量(production.ini或同等产品中的threads参数)
1 2 3 4 5 | t=(p*0.8)/q t - number of threads p - number of connections available in your database q - number of processes |
还请注意,应将sqlalchemy.pool_size参数(如果使用sqlalchemy http://www.sqlalchemy.org/)赋予与t相同的值。
加号:
要防止Python进程在重新启动时同时访问您的production.ini,从而导致"锁定",请在[uwsgi]部分中添加" lazy-apps = true"参数。仅当您的系统开始出现问题时,才执行此操作。