1

我有一个使用 Apache 的专用服务器来监听通过 SSL 提供 API 服务的九个非标准端口 (8xxx)。端口 80 和 443 用于提供静态内容和指示其他服务状态的“监视”服务。

几天后,服务开始失败,因为 Apache 似乎将服务请求定向到监视服务而不是预期服务。重新启动 Apache 会修复此问题,直到它再次发生。

这些服务是使用 wsgi 实现的。

有一个遗留的金字塔 API 服务配置如下:

WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIDaemonProcess pyramid user=ubuntu group=ubuntu threads=4 \
   python-path=/home/ubuntu/ev_mis/lib/python2.7/site-packages
WSGIScriptAlias /mis /home/ubuntu/ev_mis/mis.wsgi

<Directory /home/ubuntu/ev_mis>
  WSGIProcessGroup pyramid
  Order allow,deny
  Allow from all
</Directory>

其他 8 个 API 服务使用 Django,配置如下:

# Built automatically on Wed Sep 25 13:59:51 2013
Listen 8325
<VirtualHost _default_:8325>
    DocumentRoot /usr/local/services/h/rb/mis/mis_site/mis_site
    Alias /media /usr/local/services/h/rb/mis/mis_site/mis_site/media
    Alias /static /usr/local/services/h/rb/mis/mis_site/mis_site/assets

    <Directory /usr/local/services/h/rb/mis/mis_site/mis_site>
        Order allow,deny
        Allow from all
    </Directory>

    SetEnv DJANGO_SETTINGS_MODULE mis_site.settings.h
    WSGIScriptAlias / /usr/local/orb_services/h/rb/mis/mis_site/mis_site/mis_site/wsgi.py
    SSLEngine On
    SSLCertificateFile    /etc/apache2/ssl/domain.crt
    SSLCertificateKeyFile /etc/apache2/ssl/domain.key
    SSLCertificateChainFile /etc/apache2/ssl/chain.crt
    SSLOptions +StrictRequire
</VirtualHost>

最后是守望先锋服务配置:

<VirtualHost *:80>

DocumentRoot /var/www
Alias /static /var/www/static
<Directory /var/www/>
    Order allow,deny
    Allow from all
</Directory>

Alias /thumbnails /var/www/thumbnails
<Directory /var/www/thumbnails>
    Order allow,deny
    Allow from all
</Directory>

WSGIScriptAlias / /var/www/overwatch/overwatch/wsgi.py

ErrorLog ${APACHE_LOG_DIR}/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

这是一个示例 wsgi.py 文件:

import os
from os.path import abspath, dirname
from sys import path
from os import environ

SITE_ROOT = dirname(dirname(abspath(__file__)))
path.append(SITE_ROOT)

from django.core.wsgi import get_wsgi_application
def application(req_environ, start_response):
    environ["DJANGO_SETTINGS_MODULE"] = req_environ.get("DJANGO_SETTINGS_MODULE",
                                                        environ.get("DJANGO_SETTINGS_MODULE",
                                                                    None))
    return get_wsgi_application()(req_environ, start_response)

例如:https : //example.com/ 产生监视状态表,而https://example.com:8123/data/产生关于其中一项服务的服务数据。

分析表明,apache 错误地将调用定向到了守望服务。例如https://example.com:8123/data/现在产生页面未找到调试跟踪显示它已由守望先锋 wsgi 服务提供。

一旦发生这种情况,它就会一直发生,直到我重新启动 apache 服务。然后一切都好几天,直到它再次发生。Apache 不报告任何配置问题并且可以正常启动/重新启动。

目前,服务器只经历了非常轻的测试流量,但它计划很快上线,我不知道如何解决这个问题......在我重新配置整个事情以使用 nginx/ 时可能会咬紧牙关并延迟启动gunicorn 而不是 apache,感觉就像一个警察。

4

1 回答 1

1

几点评论。

  • 您不应将 DocumentRoot 设置为项目代码所在的目录。如果您无意中注释掉了 WSGIScriptAlias,那么您的所有项目代码,包括带有数据库密码的设置文件,都可能被某人下载。
  • 您不能在 Apache 中使用“SetEnv DJANGO_SETTINGS_MODULE mis_site.settings.h”来指定 Django 设置模块的位置。它需要在 wsgi.py 文件中设置。
  • 你为什么不为你的 Django 站点使用 mod_wsgi 的守护进程模式呢?您将在一个进程的子解释器中运行多个实例,如果您没有正确配置 Django,则可能导致请求被错误的应用程序处理。见http://blog.dscpl.com.au/2012/10/requests-running-in-wrong-django.html

更新 1

而不是使用:

from django.core.wsgi import get_wsgi_application
def application(req_environ, start_response):
    environ["DJANGO_SETTINGS_MODULE"] = req_environ.get(
            "DJANGO_SETTINGS_MODULE". environ.get("DJANGO_SETTINGS_MODULE", None))
    return get_wsgi_application()(req_environ, start_response)

你应该使用:

from django.core.wsgi import get_wsgi_application
_application = get_wsgi_application()

def application(req_environ, start_response):
    environ["DJANGO_SETTINGS_MODULE"] = req_environ.get(
            "DJANGO_SETTINGS_MODULE", environ.get("DJANGO_SETTINGS_MODULE", None))
    return _application(req_environ, start_response)

您在每个请求上都调用 get_wsgi_application() ,这是一个坏主意。它会在每个请求上创建一个新的 WSGI 处理程序实例,这不是必需的。这样做也会搞砸New Relic等监控工具的运行。

于 2013-09-30T00:37:53.253 回答