WSGI:从守护进程接收到截断或过大的响应标头

WSGI:从守护进程接收到截断或过大的响应标头

系统配置:Apache2、Django 1.10、Python 3、Ubuntu 16.04 LTS

Django debug=True


/var/log/apache2/error.log

[52:53.057967] [wsgi:error] [pid 4303] [client 1.1.1.22:24409] Timeout when reading response headers from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.466726] [wsgi:error] [pid 4305] [client 1.1.1.10:9787] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.466729] [wsgi:error] [pid 4304] [client 1.1.1.4:18417] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.466726] [wsgi:error] [pid 4307] [client 1.1.1.22:35116] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.466756] [wsgi:error] [pid 4306] [client 1.1.1.22:19242] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.467164] [wsgi:error] [pid 4336] [client 1.1.1.4:34187] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.467212] [wsgi:error] [pid 4342] [client 1.1.1.22:28212] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py, referer: http://example.org/
[52:58.467282] [wsgi:error] [pid 4331] [client 1.1.1.22:31045] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py
[52:58.467426] [wsgi:error] [pid 4341] [client 1.1.1.70:22784] Truncated or oversized response headers received from daemon process 'example.org': /home/user/dir/project/main_app/wsgi.py, referer: http://example.org/

我不知道错误的原因。但我已将问题缩小到 Django wsgi 进程。因为服务器正确托管了静态文件。

虽然 Cloudflare 有时会显示 502:糟糕的网关错误,但服务器本身会显示 500:内部服务器错误。

我已经尝试重新启动服务器并检查 Django 的(调试)日志文件。Django 日志文件中根本没有任何错误信息。


我该如何调试该问题?由于 Django 没有记录任何内容,因此我假设该问题可能是由 wsgi 引起的。

注意:服务器之前运行良好。我做了一些更改*(已按原样恢复);Django shell 运行良好。

变化*

  1. 已安装 django-pandas、django-model-utils、numpy、scikit-learn
  2. 使用上述库的程序。(此更改已恢复为原始更改)

在其他类似的问题中,该问题是由于上传大文件时引起的。

答案1

问题的原因是numpy

众所周知,Python C 扩展模块(例如 numpy)在 mod_wsgi 下使用时会导致超时。

来源:肖恩·F从守护进程读取响应头时超时

我在初始搜索中没有找到类似的问题,作者回答并解释了mod_wsgi这一点 -

一些使用 C 扩展模块的 Python 第三方软件包(包括 scipy 和 numpy)只能在 Python 主解释器中使用,不能像 mod_wsgi 默认使用的那样在子解释器中使用。结果可能是线程死锁、行为不正确或进程崩溃。

来源:格雷厄姆·邓普尔顿安装 scipy 后,apache + mod_wsgi 无响应

解决方案

将以下行添加到您的httpd.conf. 在我的例子中,文件是/etc/apache2/apache2.conf.

WSGIApplicationGroup %{GLOBAL}

答案2

正如其他人提到的,这是由于进程因多种潜在原因而崩溃造成的。其中一个原因是某些 Python 依赖项不是线程安全的。

如果这是问题所在,一种解决方法是切换 Apache 的 MPM 类型。prefork 类型不使用线程,因此如果问题是 numpy 由于线程误用而崩溃,那么这应该可以解决问题。worker 和 event 类型使用较少的内存,但也使用线程,因此它们可能会遇到此错误。

要确定您当前正在使用的类型,请运行:

apachectl -V | grep -i mpm

如果您看到Server MPM: prefork,则表示您已在使用 prefork,这意味着错误的原因可能是其他原因。如果它显示“worker”或“event”,则您可以通过运行以下命令切换到 prefork:

sudo a2dismod mpm_event
sudo a2dismod mpm_worker
sudo a2enmod mpm_prefork
sudo service apache2 restart

请注意,prefork 的主要缺点是由于它不使用线程,因此会消耗更多内存。

编辑:我后来因为其他原因遇到了这个错误。最近,这个问题是由 Ubuntu 预编译的 mod-wsgi 系统包中的一个错误以及 Python psycopg2 包中的一个错误引起的。

解决方案是从系统 mod-wsgi 切换到 Python 包,并切换到 psycopg2-binary 包:

sudo apt purge libapache2-mod-wsgi*
sudo apt install apache2-dev
pip uninstall psycopg2
pip install mod_wsgi psycopg2-binary

我还必须通过在顶部添加以下内容来更新我的 apache 站点配置文件:

LoadModule wsgi_module /usr/local/myproject/.env/lib/python2.7/site-packages/mod_wsgi/server/mod_wsgi-py27.so

并将我的 WSGIDaemonProcess 语句更改为使用 python-home 而不是 python-path,如下所示:

WSGIDaemonProcess myproject python-home=/usr/local/myproject/.env processes=5 threads=15 display-name=%{GROUP} user=www-data group=www-data

我在 Python2.7 和 Python3.7 中都遇到过这个问题,解决方案相同,但是 mod_wsgi.so 的路径发生了变化。

答案3

我在尝试使用 mod_wsgi 和 apache 运行 opencv 时也收到过类似的错误。我猜问题可能是底层 C 代码的多个线程尝试获取 GIL 并失败了。

我通过在 WSGIDaemonProcess 指令中设置threads=1 和 processes=32(在我的情况下这是合适的)解决了这个问题。

附言:虽然迟到了,但我认为它可以帮助到某些人。

答案4

就我而言,问题是pymongo 和 PHP. 正如这个 GitHub 问题中所述https://github.com/GrahamDumpleton/mod_wsgi/issues/351

如果 PHP 正在加载 MongoDB 的客户端,则可能会 [产生冲突]。(...) PHP 通常会预加载所有扩展。无论托管应用程序是否使用它都无所谓。

我解决的方法是:

  1. 我从 mod_wsgi-express 运行了我的 flask 应用程序:mod_wsgi-express start-server api.wsgi --user=www-data --group=www-data --host=0.0.0.0 --port=8443
  2. 然后,在我的 中httpd.conf,我使用以下命令将所有流量重定向到我的 flask 应用程序别名:
SSLEngine on
SSLProxyEngine On
ProxyPass /api http://localhost:8443/
ProxyPassReverse /api http://localhost:8443/

相关内容