【问题标题】:How to avoid Django sub thread being killed by uWSGI respawn如何避免 Django 子线程被 uWSGI respawn 杀死
【发布时间】:2017-01-13 03:32:46
【问题描述】:

我用 Django + uWSGI 创建了一个 Web 服务器。基本流程是:当收到请求时,Django会通过python内置lib“Threading”发起一个子线程来异步写入db,在主线程中它会立即响应回客户端。

如何,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()

【问题讨论】:

  • 听起来像是 XY 问题。你为什么首先使用线程?
  • 嗨丹尼尔,我不知道什么是 XY 问题。你能分享更多信息吗?我这里使用多线程的原因只是为了尽快响应客户端,使其不会被db操作阻塞。 @丹尼尔罗斯曼
  • xyproblem.info - 即您不是在询问您的实际问题。正如您所发现的,在您无法管理的环境中,手动管理线程很少是一个好主意。使用像Celery 这样的离线工作系统。
  • 谢谢,丹尼尔。芹菜完全可以满足我的要求。您能否在下面发布您的答案以便我接受?
  • 如果你只需要这样的东西,Celery 是重量级的。如果你有 uwsgi,你可以使用它的 spooler 进程,并导入 uwsgidecorators 让它变得非常简单。

标签: python django multithreading uwsgi


【解决方案1】:

在您无法管理的环境中,手动处理线程很少是个好主意。

您应该使用像Celery 这样的离线工作系统。

【讨论】:

    【解决方案2】:

    在我的情况下,这个问题是由于我的数据库的某些操作延迟引起的。

    我使用 uWSGIPyramid (http://docs.pylonsproject.org/projects/pyramid/en/latest/)。由于您使用的是 Django (Python),因此该解决方案很可能对您有用。

    下面引用的设置位于配置文件 production.ini[uwsgi] 部分)(http://uwsgi-docs.readthedocs.io/en/latest/Options.html)。

    我使用以下规则“解决”了这个问题。该规则“解决”了问题,因为它大大减少了它的发生。到目前为止,我还没有看到任何可以完全避免它的东西。我的性能也有所提高(需要测试,但我们评估为一个很好的改进)。解决方案基本上是根据数据库允许的连接数增加线程数(您也可以增加数据库允许的连接数)。

    规则:

    定义进程的数量(processes 参数在您的 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,从而导致“锁定”,请在 [uwsgi] 部分添加“lazy-apps=true”参数。 只有在您的系统开始出现问题时才这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多