uWSGI的几个使用技巧

uWSGI基本上是python做web服务的不二选择了,但似乎项目的开发者比较热衷于其新功能开发,对其使用文档还是相当缺乏的。

安装:

Ubuntu

添加ppa,安装。 目前只有Lucid, Maverick, Natty几个版本还需要添加,以后版本都在官方原,直接apt-get install即可。

1
2
3
add-apt-repository ppa:uwsgi/release
apt-get update
apt-get install uwsgi-python

Debian

目前Debian sid已经收录了uwsgi,一般服务器安装的testing/stable,只能自己修改apt的配置,从sid里面port过来。

注意:以下操作可能毁掉您的整个debian包系统。以下命令仅在Debian wheezy,即目前的testing运行测试安装过,如果你的是squeeze,自己修改01all那里 Pin: release a=squeeze 一行,但不保证能够正常运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo "deb http://ftp.tw.debian.org/debian sid main non-free contrib" >> /etc/apt/sources.list
cat > /etc/apt/preferences.d/01all << EOF
Package: *
Pin: release a=testing
Pin-Priority: 1000
EOF
 
cat > /etc/apt/preferences.d/02uwsgi << EOF
Package: uwsgi
Pin: release a=sid
Pin-Priority: 1010
EOF
 
apt-get update
apt-get install uwsgi uwsgi-core uwsgi-plugin-python

Centos, RHEL, Fedora, …

You’re on your own, linux user.

配置

常见配置文件:

1
2
3
4
5
6
7
8
9
10
11
cat > /etc/uwsgi/apps-enabled/test.ini << EOF
[uwsgi]
chmod-socket = 666
limit-as = 256
processes = 6
max-request = 2000
memory-report = true
enable-threads = true
virtualenv = /somewhere/to/your/virtualenv
wsgi-file = /home/somewhere/app.py
EOF

用ini方式的配置是比xml的容易写多了。具体配置说明请看Doc

默认的sock文件在/var/run/uwsgi/test/socket

配合nginx使用的配置文件:

1
2
3
4
5
6
7
8
9
10
cat > /etc/nginx/sites-enabled/test << EOF
server {
        listen   80;
        server_name host.domain.com;
        location / {
                include uwsgi_params;
                uwsgi_pass unix:///var/run/uwsgi/test/socket;
        }
}
EOF

切换Python版本

系统中可能安装有多个版本的Python,又或者同个系统里面有的app跑python3, 有的跑python2.6 stackless, 有的跑python2.7…

uwsgi 是通过plugin的方式加载不同的python解析器的,debian的uwsgi-plugin-python包里面提供了python26_plugin.so, python27_plugin.so, 不过uwsgi如果在app配置里面没有plugins参数指定使用哪个时候,会尝试加载/usr/lib/uwsgi/plugins/python_plugin.so,这个文件在debian下是个链接文件,可以运行update-alternatives --config uwsgi-plugin-python命令来修改这个默认版本。

源里面没有提供stackless python的plugin,只能自己编译了,还好非常简单:

/path/to/your/stackless/python uwsgiconfig.py --plugin plugins/stackless

然后把生成的python_stackless.so放到/usr/lib/uwsgi/plugins 就能被uwsgi加载了。

其他plugin的编译基本都这样,看源代码里面的plugins目录。

代码

使用uwsgi运行代码的时候,可以import uwsgi模块,和uwsgi进行一定的交互。

uwsgi 的源代码包当中有个uwsgidecorators.py,提供了多数的uwsgi接口,描述文档在此。以下是几个典型应用。

自动重载

好一些web框架都有检测修改了源文件就自动重新加载的功能,但是在uwsgi里面这个方法是不好用了。

Django

加入以下代码:

1
2
3
4
5
6
7
8
import uwsgi
from uwsgidecorators import timer
from django.utils import autoreload
 
@timer(3)
def change_code_gracefull_reload(sig):
    if autoreload.code_changed():
        uwsgi.reload()

Bottle

Bottle 的reload是它内置基础web服务器的功能,在uwsgi里面只能自己写代码监控。

想要简单很难做到完美:

1
2
3
4
5
6
7
from uwsgidecorators import filemon
 
filemon('/tmp/foo')(uwsgi.reload)
filemon('/tmp/foo2')(uwsgi.reload)
filemon('/tmp/foo3')(uwsgi.reload)
filemon('/tmp/foo4')(uwsgi.reload)
filemon('/tmp/foo5')(uwsgi.reload)

于是这些文件出现修改的时候,就自动reload。其实你可以自己加入调用uwsgi.reload()的响应。

pylons, web.py, cherrypy ..

程序员自己研究去。

threading

原来使用内置线程做的异步程序会发现在uwsgi,里面的线程好像都没启动了、数据库没有连接了……原因是uwsgi加载了代码后,fork出多个子进程,子进程里面的线程如果没有被再度激活,是不工作的。

有两个方法,一是在这个app的配置里面加上:

lazy = true

这样代码会在子进程fork了之后才开始加载。

二是使用uwsgi模块的api,uwsgidecorators 里面有相应的装饰器,这样uwsgi会在fork之后自动调用你要重新启动的线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
from uwsgidecorators import postfork
 
@postfork
def reconnect_to_db():
    myfoodb.connect()
 
@postfork
def restart_threads():
    global thread1, thread2
    thread1 = MyThread1()
    thread1.start()
    thread2 = MyThread2()
    thread2.start()

监控

虽然uwsgi 默认带了SNMP功能,可以给外部监控其运行情况,但uwsgi的源码包里面带了个uwsgistatus.py文件,里面简单的提供了读取uwsgi模块的属性形成的报告。 可以把里面的代码copy到app项目里面,作为一个简单的监控数据。

2011-11-24_19-04-14.png

Reference

以上部分代码取自uWSGI Wiki页面

文章分类 Python, web技术 标签: ,
One comment on “uWSGI的几个使用技巧
  1. alswl说道:

    托你的福,我看到了几个重要参数,终于把配置文件从 nginx 的耦合解了出来。

    [uwsgi]
    socket = /tmp/moin.sock
    chmod-socket = 660
    master = true
    plugins = python
    processes = 4
    uid = webapp
    gid = www-data
    virtualenv = /home/webapp/.virtualenvs/moin/
    chdir = /home/webapp/app/moin/
    wsgi-file = moin_wsgi.py