如何避免 Django 子线程被 uWSGI respawn 杀死
How to avoid Django sub thread being killed by uWSGI respawn
我用 Django + uWSGI 创建了一个网络服务器。基本流程是:当收到请求时,Django会通过python内置库"Threading"发起一个子线程异步写入db,在主线程中会立即响应回client。
如何,uWSGI 有时会重新生成工作进程(也许当进程没有请求处理时?),这导致后台子线程即使尚未完成也被杀死。任何避免 uWSGI 不重生具有 运行 子线程的工作进程的线索?
uWSGI 重生日志:
DAMN ! worker 4 (pid: 31161) died, killed by signal 9 :( trying respawn ...
uWSGI ini 配置(版本 2.0.12):
[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中:
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()
在 views.py 中:
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).
我"solved"这个问题使用下面的规则。这决定了 "solve" 这个问题,因为它大大减少了它的发生。到目前为止,我还没有看到任何可以完全避免它的东西。我的性能也有所提高(需要测试,但我们评估为良好的改进)。解决方案基本上是根据数据库允许的连接数增加线程数(您也可以增加数据库允许的连接数)。
规则:
定义进程的数量(进程参数在你的production.ini或等价物中)
q=n*2
q - number of processes
n - number of CPUs/cores
定义线程的数量(threads 参数在您的 production.ini 或等效项中)
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 导致 "lock" 在 [uwsgi] 部分添加 "lazy-apps=true" 参数。 仅当您的系统开始出现问题时才执行此操作。
我用 Django + uWSGI 创建了一个网络服务器。基本流程是:当收到请求时,Django会通过python内置库"Threading"发起一个子线程异步写入db,在主线程中会立即响应回client。
如何,uWSGI 有时会重新生成工作进程(也许当进程没有请求处理时?),这导致后台子线程即使尚未完成也被杀死。任何避免 uWSGI 不重生具有 运行 子线程的工作进程的线索?
uWSGI 重生日志:
DAMN ! worker 4 (pid: 31161) died, killed by signal 9 :( trying respawn ...
uWSGI ini 配置(版本 2.0.12):
[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中:
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()
在 views.py 中:
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).
我"solved"这个问题使用下面的规则。这决定了 "solve" 这个问题,因为它大大减少了它的发生。到目前为止,我还没有看到任何可以完全避免它的东西。我的性能也有所提高(需要测试,但我们评估为良好的改进)。解决方案基本上是根据数据库允许的连接数增加线程数(您也可以增加数据库允许的连接数)。
规则:
定义进程的数量(进程参数在你的production.ini或等价物中)
q=n*2
q - number of processes
n - number of CPUs/cores
定义线程的数量(threads 参数在您的 production.ini 或等效项中)
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 导致 "lock" 在 [uwsgi] 部分添加 "lazy-apps=true" 参数。 仅当您的系统开始出现问题时才执行此操作。