Django + Apache + ModWSGI无限期挂起

时间:2017-10-27 06:40:16

标签: python django apache mod-wsgi

我在Ubuntu 16上有Apache 2.4.18 + ModWSGI提供的Django 1.11站点,它无限期挂起。奇怪的是,如果我停止Apache,那么它才会返回请求,这会使页面完美呈现,这意味着Django正确地返回了请求,但是有些东西会阻止Apache发送数据。< / p>

我的Apache site.conf:

<VirtualHost *:80>
    ServerName www.mysite.com
    ServerAlias www.mysite.com
    ServerAdmin sysadmin@mysite.com
    DocumentRoot /usr/local/mysite

    AllowEncodedSlashes On

    Alias /media/ /usr/local/mysite/media/
    Alias /static/ /usr/local/mysite/static/

    <Directory /usr/local/mysite>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        Allow from all
        # New directive needed in Apache 2.4.3.
        Require all granted
    </Directory>

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    LogLevel debug
    ErrorLog ${APACHE_LOG_DIR}/mysite-error.log
    CustomLog ${APACHE_LOG_DIR}/mysite-access.log combined

    # Stop GIL deadlocks from crashing Python/Modwsgi due to Python C-extensions?
    # Without this, you may get a "Premature end of script" error.
    # https://code.google.com/p/modwsgi/wiki/ApplicationIssues#Python_Simplified_GIL_State_API
    WSGIApplicationGroup %{GLOBAL}

    WSGIDaemonProcess www.mysite.com python-path=/usr/local/mysite/.env/lib/python2.7/site-packages processes=1  display-name=%{GROUP} user=www-data group=www-data
    WSGIProcessGroup www.mysite.com
    WSGIScriptAlias / /usr/local/mysite/wsgi/mysite.wsgi

    <Directory /usr/local/mysite/wsgi>
        Order allow,deny
        Allow from all
    </Directory>

</VirtualHost>

我的Django wsgi:

import os
import time
import traceback
import signal
import sys

from django.core.wsgi import get_wsgi_application

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings.settings'
os.environ['CELERY_LOADER'] = 'django'

sys.path.append(os.path.join(os.path.realpath(os.path.dirname(__file__)), '../src'))
sys.path.append(os.path.join(os.path.realpath(os.path.dirname(__file__)), '../src/mysite'))

try:
    application = get_wsgi_application()
    print 'WSGI without exception'
except Exception:
    print 'handling WSGI exception'
    # Error loading applications
    if 'mod_wsgi' in sys.modules:
        traceback.print_exc()
        os.kill(os.getpid(), signal.SIGINT)
        time.sleep(2.5)

我的Apache日志中唯一感兴趣的是几行:

[Fri Oct 27 02:37:08.079977 2017] [wsgi:error] [pid 14053:tid 139644805011200] [client 10.182.122.159:45695] Timeout when reading response headers from daemon process 'www.mysite.com': /usr/local/mysite/wsgi/mysite.wsgi

显然,似乎某些东西没有得到正确的信号,导致它等到超时发生,但我无法弄清楚原因是什么。我已经尝试重构我的Apache配置,并禁用我的Django应用程序中可能超时的部分,但没有任何工作。我该如何诊断?

1 个答案:

答案 0 :(得分:0)

您的请求很可能是阻止而且永远不会返回。与信号无关,或至少Apache自己使用信号。关机信号可能会中断您的请求被阻止的某些系统调用。

WSGIDaemonProcess指令添加到选项:

request-timeout=60

并监视日志以查看mod_wsgi守护程序进程是否因请求超时而重新启动。

因为您使用默认值为15个线程的单个进程,因为请求超时如何作为所有请求处理程序的平均值应用,如果只有一个请求处理程序无限期地阻塞,则强制重启最多需要15分钟过程如果多个请求被阻止,那么将比这更快。

我在这里假设60秒超出了你的预期。如果您的请求设置得更低,则应将其设置得更低。

您的WSGI脚本文件中也不需要try/except/kill个东西。而不是添加WSGIDaemonProcess选项:

startup-timeout=15