Nginx / Apache / WSGI / Django - 意外引发 500 错误(Nginx 上为 499)

Posted

技术标签:

【中文标题】Nginx / Apache / WSGI / Django - 意外引发 500 错误(Nginx 上为 499)【英文标题】:Nginx / Apache / WSGI / Django - Unexpected raising 500 errors (499 on Nginx) 【发布时间】:2016-08-12 04:19:00 【问题描述】:

我的 Django 服务器在 Webfaction 托管上存在问题。对于某些请求(每天 500.000 的大约 1.000 个请求),我可以在访问日志中看到错误。在 nginx 日志中我可以看到代码为“499”的请求,在 apache 日志中它们有“500”错误代码。

奇怪的是我在我的 django 日志中没有看到任何问题(通常我收到的邮件除了堆栈跟踪)。你能帮我吗,是什么导致了这种奇怪的行为?

在收到超出托管内存限制的问题后,我开始调查日志。似乎我的应用程序有一些内存泄漏,因为我可以看到使用的内存在缓慢上升。因此,我尝试通过优化我的 wsgi 进程、线程并尝试设置最大请求参数来进行快速修复。之后我会调查内存泄漏的原因。

我的基础设施如下:

Nginx - 前端服务器(由 Webfaction 运营) Apache/2.4.16,带有 mod_wsgi 4.4.13/Python 3.4 Django 1.8.12

我的 httpd.conf 如下:

ServerRoot "/home/quick/webapps/citaty/apache2"

LoadModule authz_core_module modules/mod_authz_core.so
LoadModule dir_module        modules/mod_dir.so
LoadModule env_module        modules/mod_env.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module       modules/mod_mime.so
LoadModule rewrite_module    modules/mod_rewrite.so
LoadModule setenvif_module   modules/mod_setenvif.so
LoadModule wsgi_module       modules/mod_wsgi.so
LoadModule unixd_module      modules/mod_unixd.so

LogFormat "%X-Forwarded-Fori %l %u %t %Hosti \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\" %T %D" combined
CustomLog /home/quick/logs/user/access_citaty.log combined
ErrorLog /home/quick/logs/user/error_citaty.log

Listen 21628
KeepAlive Off
SetEnvIf X-Forwarded-SSL on HTTPS=1
ServerLimit 1
StartServers 1
MaxRequestWorkers 10
MinSpareThreads 1
MaxSpareThreads 5
ThreadsPerChild 10
MaxRequestsPerChild 1000

WSGIRestrictEmbedded On
WSGILazyInitialization On

<VirtualHost *>
    ServerName domain.com

    CustomLog /home/quick/logs/user/access_citaty.log combined
    ErrorLog /home/quick/logs/user/error_citaty.log

    WSGIDaemonProcess citaty processes=5 threads=1 maximum-requests=1000 python-path=/home/quick/webapps/citaty:/home/quick/webapps/citaty/lib/python3.4/site-packages display-name=%GROUP
    WSGIProcessGroup citaty
    WSGIScriptAlias / /home/quick/webapps/citaty/apache2/conf/citaty.wsgi

</VirtualHost>

<VirtualHost *>
    ServerName domain2.com

    CustomLog /home/quick/logs/user/access_citaty_laska.log combined
    ErrorLog /home/quick/logs/user/error_citaty_laska.log

    WSGIDaemonProcess citaty_laska processes=1 threads=1 maximum-requests=1000 python-path=/home/quick/webapps/citaty:/home/quick/webapps/citaty/lib/python3.4/site-packages display-name=%GROUP
    WSGIProcessGroup citaty_laska
    WSGIScriptAlias / /home/quick/webapps/citaty/apache2/conf/citaty_laska.wsgi
</VirtualHost>

我的 django 日志设置如下:

LOGGING = 
    'version': 1,
    'disable_existing_loggers': False,
    'filters': 
        'require_debug_false': 
            '()': 'django.utils.log.RequireDebugFalse',
        ,
        'require_debug_true': 
            '()': 'django.utils.log.RequireDebugTrue',
        ,
    ,
    'handlers': 
        'file': 
            'level': 'INFO',
            'filters': ['require_debug_false'],
            'class': 'logging.FileHandler',
            'filename': '/home/quick/logs/user/django_citaty.log',
        ,
        'file_jobs': 
            'class': 'logging.FileHandler',
            'filename': '/home/quick/logs/user/django_jobs.log',
        ,
        'mail_admins': 
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        ,
        'console': 
            'class': 'logging.StreamHandler',
        ,
    ,
    'loggers': 
        'django': 
            'handlers': ['file', 'mail_admins'],
        ,
        'py.warnings': 
            'handlers': ['file'],
        ,
        'citaty.sources.crawlers.base': 
            'level': 'INFO',
            'handlers': ['file_jobs', 'console'],
        ,

    ,

【问题讨论】:

【参考方案1】:

一个月前我曾经遇到过这个问题。突然 nginx 会开始抛出 499 错误代码。

当客户端发出请求时,nginx向uwsgi请求响应,有时uwsgi响应时间过长,用户认为请求慢而尝试刷新或再次调用,nginx然后抛出499错误码。

可能的原因:-

    Uwsgi 工作程序消耗相当多的 RAM。检查 uwsgi 配置文件中有多少个工人。确保根据您的系统设置将 uwsgi 工作进程限制为适当的数量。 增加 nginx 工作程序连接。默认非常低。这会导致连接断开,从而导致 500 错误。检查 nginx 中的 connection_timeout 设置。它通常为 60 秒。您可以将其减少到 25 秒左右,以确保 nginx 已准备好接受更多连接。

我通过增加服务器 RAM 解决了这个问题,还添加了一个负载平衡器以确保一台服务器上没有繁重的负载。 此外,对 uwsgi ini 文件和 nginx.conf 进行了一些更改

下面是我的uwsgi设置文件-

[uwsgi]
project =xxxxxx
base = /home/ubuntu

chdir = %(base)/xxxxxxx/server
home = %(base)/envs/api
module = %(project).wsgi:application

master = true
cheaper-algo = spare
cheaper = 2
cheaper-initial = 3
cheaper-step = 2
processes = 20
workers = 20
max-requests = 1000

socket = %(base)/xxxx/server/%(project).sock
chmod-socket = 664
vacuum = true
logto=/tmp/uwsgi.log

我的 nginx.conf-

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events 
    worker_connections 2048;
    # multi_accept on;

底线 - 这几乎总是一个内存问题。重新检查您的代码是否存在内存泄漏。确保在生产环境中的 settings.py 中 DEBUG=False。使用缓存来减少服务器响应时间。

【讨论】:

感谢您的回复。我检查了错误请求的记录响应时间,在这种情况下似乎不是响应时间慢的问题(错误响应需要不到 0.5 秒)。但是,正如您所写的那样,工人数量可能存在问题。我会尝试增加进程和线程的数量,我会看到的。

以上是关于Nginx / Apache / WSGI / Django - 意外引发 500 错误(Nginx 上为 499)的主要内容,如果未能解决你的问题,请参考以下文章

Nginx / Apache / WSGI / Django - 意外引发 500 错误(Nginx 上为 499)

Apache + mod_wsgi 与 nginx + gunicorn

通过 Nginx 反向代理在 Apache 中使用多个 WSGI 挂载点

使用 DotCloud 使用 apache + mod_wsgi + postgresql + nginx + memchache 部署 Django 应用程序

Uwsgi Nginx Apache select poll epoll

如何部署Apache2+mod_wsgi+flask?