apache部署多个互相依赖的项目

项目中需要将多个 Django 项目需要部署在同一个 Apache2 的 VirtualHost 下面。却碰到了一个棘手的问题,就是发现这些 Django 项目共用了一个 Python 运行环境。先来看我的配置文件:

<VirtualHost *:80>
WSGIScriptAlias /a /path/to/project/a.wsgi
WSGIScriptAlias /b /path/to/project/b.wsgi
</VirtualHost>

 

看起来很简洁明了。即 VirtualHost *:80 的 /a 路径指向 a 项目,/b 路径指向 b 项目。

但是实际运行的时候问题来了:

apache 报 500 错误,看 /var/log/apache2/erro.log 发现有如下错误:

[Mon Aug 06 17:30:47 2012] [error] [client ::1] mod_wsgi (pid=12294): Exception occurred processing WSGI script '/path/to/project/a.wsgi'.
[Mon Aug 06 17:30:47 2012] [error] [client ::1] Traceback (most recent call last):
[Mon Aug 06 17:30:47 2012] [error] [client ::1]   File "/usr/local/lib/python2.6/dist-packages/Django-1.4.1-py2.6.egg/django/core/handlers/wsgi.py", line 219, in __call__
[Mon Aug 06 17:30:47 2012] [error] [client ::1]     self.load_middleware()
[Mon Aug 06 17:30:47 2012] [error] [client ::1]   File "/usr/local/lib/python2.6/dist-packages/Django-1.4.1-py2.6.egg/django/core/handlers/base.py", line 39, in load_middleware
[Mon Aug 06 17:30:47 2012] [error] [client ::1]     for middleware_path in settings.MIDDLEWARE_CLASSES:
[Mon Aug 06 17:30:47 2012] [error] [client ::1]   File "/usr/local/lib/python2.6/dist-packages/Django-1.4.1-py2.6.egg/django/utils/functional.py", line 184, in inner
[Mon Aug 06 17:30:47 2012] [error] [client ::1]     self._setup()
[Mon Aug 06 17:30:47 2012] [error] [client ::1]   File "/usr/local/lib/python2.6/dist-packages/Django-1.4.1-py2.6.egg/django/conf/__init__.py", line 42, in _setup
[Mon Aug 06 17:30:47 2012] [error] [client ::1]     self._wrapped = Settings(settings_module)
[Mon Aug 06 17:30:47 2012] [error] [client ::1]   File "/usr/local/lib/python2.6/dist-packages/Django-1.4.1-py2.6.egg/django/conf/__init__.py", line 95, in __init__
[Mon Aug 06 17:30:47 2012] [error] [client ::1]     raise ImportError("Could not import settings '%s' (Is it on sys.path?): %s" % (self.SETTINGS_MODULE, e))
[Mon Aug 06 17:30:47 2012] [error] [client ::1] ImportError: Could not import settings 'b.settings' (Is it on sys.path?): No module named b.settings

 

很明显,a 项目的 wsgi 程序在找 b 项目的 settings 模块。正常情况下,a 项目的 wsgi 程序找的应该是 a 项目的 settings 模块,而 b 项目的 wsgi 程序找的也应该是 b 项目的 settings 模块。

这里为什么会错了呢?

再看 a 项目的 wsgi 程序代码 (b 也一样):

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "a.settings")

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

 

可以看出在一开始,设置了一个叫 DJANGO_SETTINGS_MODULE 的环境变量,b 项目设的是 b.settings。 从上面 apache 的 error log 中可以看出两个不相干的项目在找对方的 settings 模块。因此猜测是两个 wsgi 进程共用了一个 python 运行环境,导致后执行的 b 程序重写了 a 程序的 DJANGO_SETTINGS_MODULE 环境变量。因此下一次请求来的时候,a 项目按变量中的设置去找了 b 项目中的模块。

猜测了原因后开始对症下药,发现 mod_wsgi 有一个 process group 的概念。用不同的 process group 把不同的 django 项目运行环境分开即可。

配置方法如下:

<VirtualHost *:80>

    WSGIDaemonProcess a processes=2 threads=5
    WSGIDaemonProcess b processes=2 threads=5

    WSGIScriptAlias /a '/path/to/project/a.wsgi'
    WSGIScriptAlias /b '/path/to/project/g.wsgi'

    <Location /a>
        WSGIProcessGroup a
        WSGIApplicationGroup %{GLOBAL}
    </Location>

    <Location /b>
        WSGIProcessGroup b
        WSGIApplicationGroup %{GLOBAL}
    </Location>

</VirtualHost>

 

简单地解释下,大概就是建立两个 WSGIDaemonProcess,a 和 b。然后指定 a 项目用 a 这个 Group,b 项目用 b 这个 Group,大家就互不相干了。

Update:

在最新的项目中,发现这样也会出现问题,两个环境还是会混淆,于是又加了一层保险,把两个项目的 settings 环境变量的名字给改了,改完后 wsgi.py 文件变成这样(project b 也同样地改):

import os
import site
import django.conf

django.conf.ENVIRONMENT_VARIABLE = 'DJANGO_A_SETTINGS_MODULE'

os.environ.setdefault('DJANGO_A_SETTINGS_MODULE', 'project_a.settings')

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

 

posted @ 2015-08-31 11:48  雅思敏  阅读(390)  评论(0编辑  收藏  举报