关于作者

uwsgi的多站点配置

廖雪峰 / 编程 / ... / Reads: 1

uwsgi似乎是目前部署python站点最方便的组件了。配置单一网站非常简单,参考Debian Lenny安装nginx+uwsgi可轻松完成。不过,同一个服务器部署多个站点就稍微复杂一点。经过一个晚上的折腾,终于配置成功。

这里的多站点是指使用同一Nginx和uwsgi主进程服务的多个站点,通常以域名区分。注意,不是使用多个uwsgi主进程实现。

首先,多站点需要Python的virtualenv支持。这个virtualenv很强大,基本作用是帮助我们隔离出一个干净的Python环境,例如,环境A安装了Django 0.9,环境B安装了Django 1.1,如果没有virtualenv,则需要自己管理这些包的路径。有了virtualenv,各个Python环境互不影响,多个站点使用各自的Python环境,同一组件的不同版本不会冲突。virtualenv的实现方式也很简单,就是复制一份完整的Python环境到单独的目录,并设置若干环境变量。一旦进入某一env,所有操作均在该目录下进行,不会影响其他env环境。所以virtualenv实乃开发必备的武器。

安装virtualenv需要root或sudo权限:

# easy_install virtualenv

然后,创建一个env环境:

# mkdir /srv/vpython
# cd /srv/vpython
# virtualenv --no-site-packages shici

现在,就创建了一个虚拟的Python环境,名为shici,加上--no-site-packages是告诉virtualenv不从系统Python的site-packages下复制第三方的包。

进入虚拟shici环境:

# cd /srv/vpython/shici
# source bin/activate

会看到提示符前面多了一个(shici)。现在运行python,可以看到sys.path已经更改为/srv/vpython/shici目录下的各个包。

运行easy_install安装需要的包,现在安装的包将全部安装到shici环境中,不影响系统Python环境和其他env环境。

装完需要的包后,用deactivate命令退出虚拟环境。

第二步,修改/etc/init.d/uwsgi启动脚本,以vhost模式启动:

#if [ -f /etc/default/uwsgi ] ; then
#        . /etc/default/uwsgi
#fi

#DAEMON_OPTS="-s 127.0.0.1:9001 -C -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pythonpath $PYTHONPATH --module $MODULE"
DAEMON_OPTS="-s 127.0.0.1:9001 -C -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --no-site --vhost"

uwsgi启动脚本可以从Linode网站下载,请参考Debian Lenny安装nginx+uwsgi一文。

/etc/default/uwsgi配置文件不再需要,因此注释掉相应的部分。

将原有的DAEMON_OPTS注释掉,再添加一行,参数为--no-site --vhost。

第三步,修改nginx配置文件,对www.shi-ci.com的配置为:

...
    server {
        listen 80;
        server_name www.shi-ci.com;
        charset utf-8;

        access_log /srv/logs/access-www.shi-ci.com.log;
        error_log /srv/logs/error-www.shi-ci.com.log;

        location / {
            include uwsgi_params;
            uwsgi_param UWSGI_SCRIPT shici_app;
            uwsgi_param UWSGI_PYHOME /srv/vpython/shici;
            uwsgi_pass 127.0.0.1:9001;
        }
        location /static {
            root /srv/www.shi-ci.com/html/;
        }
        error_page 500 502 503 504  /50x.html;
        location = /50x.html {
            root html;
        }
    }
...

参数UWSGI_PYHOME指定了虚拟env的Python环境目录,UWSGI_SCRIPT则是包含application的入口模块。这里配置的shici_app,uwsgi将在PYTHONPATH中搜索模块shici_app.py。

测试发现,直接修改虚拟Python环境的bin/activate文件来export PYTHONPATH似乎不起作用,这样我们的站点目录/srv/www.shi-ci.com/py就无法被uwsgi搜索到。一个曲线解决方案是在虚拟的shici Python环境中直接创建一个shici_app.py的文件,位于/srv/vpython/shici/lib/python2.5/目录下,内容如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/srv/www.shi-ci.com/py')

from app import application

这个shici_app.py的作用就是先将网站目录添加到sys.path中,然后,从app模块导入application即可。app.py位于/srv/www.shi-ci.com/py/,里面有类似application=app.wsgifunc()的语句。

所以真正的站点入口文件位于/srv/www.shi-ci.com/py/app.py,但是由于虚拟Python环境默认不包含该目录,会导致uwsgi导入app模块失败,因此,编写一个shici_app的wrapper模块,位于虚拟环境/srv/vpython/shici/lib/python2.5/目录下,让uwsgi导入shici_app模块,就可以顺利导入app模块。

要添加第二个站点,重复上述步骤,创建一个新的env,安装必要的包,然后配置nginx即可。

最后,重启uwsgi和nginx生效。

Comments

Make a comment

WARNING: You are using an old browser that does not support HTML5. Please choose a modern browser (Chrome / Microsoft Edge / Firefox / Sarafi) to get a good experience.