在这之前我的youflog 是用fcgi的方式部署在nginx上的.
fcgi不是python web server的标准,wsgi才是,wsgi的实现方法有很多,其中uwsgi算是很优秀的一个。
http://projects.unbit.it/uwsgi/
uwsgi是一个用c语言开发的一个wsgi服务器,旨在提供专业的 Python web应用发布和开发.
所以决定把fcgi改成uwsgi。
uwsgi的安装
1.下载uwsgi 当前最新的版本是 0.9.6.6
2.编译uwsgi
   由于uwsgi需要libxml2库的支持 需要将libxml2先安装上 apt-get install python-dev libxml2-dev
tar zxvf uwsgi-0.9.6.6.tar.gz
cd uwsgi-0.9.6.6
make -f Makefile.Py26  (指定你python的版本,如果你的python是3.0 就应该是 make -f Makefile.Py3.0)
编译成功后就会在当前目录下生成一个uwsgi的可执行文件
cp uwsgi /usr/sbin/uwsgi
安装Nginx
nginx在0.8的版本以前是不支持wsgi的 因此在编译nginx的时候需要指定uwsgi路径
下面是针对 ubuntu 用户
sudo add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx
最后就是把django的应用部署到nginx上去
cd /etc/nginx/sites-available
vi default

server {
        listen   0.0.0.0:80;
## listen for ipv4; this line is default and implied
       #listen   [::]:80 default ipv6only=on; ## listen for ipv6

        location / {
             include uwsgi_params;

            uwsgi_pass 0.0.0.0:8080;
        }


        location /favicon.ico {
                alias
/opt/youflog/static/favicon.ico;
        }
       #error_page 404 /404.html;
}
配置就是location / {...} 部分 比cgi的的简单了许多
运行uwsgi
cd /opt/youflog

uwsgi -s 0.0.0.0:8080 -M -d /var/log/uwsgi.log --pythonpath=`pwd`
--module=wsgi
运行nginx
nginx -s reload
在浏览器中输入http://localhost , 完成.
from http://iyouf.info/nginx-uwsgi-youflog.html
-------------------------------------------------------

配置Nginx+uwsgi更方便地部署python app

个人觉得php最方便的就是deployment了,只要把php文件丢到支持php的路径里面,然后访问那个路径就能使用了;无论给主机添加多少php应用,只要把目录改好就没你的事了,完全不用关心php-cgi运行得如何,deployment极为方便。
反观python,部属起来真是头痛,常见的部署方法有:
  1. fcgi:用spawn-fcgi或者框架自带的工具对各个project分别生成监听进程,然后和http服务互动
  2. wsgi:利用http服务的mod_wsgi模块来跑各个project
无论哪种都很麻烦,apache的mod_wsgi配置起来很麻烦,内存占用还大,如果要加上nginx作为静态页面的服务器那就更麻烦了;反正我 的应用基本上到后来都是是各个project各自为战,且不说管理上的混乱,这样对负载也是不利的,空闲的project和繁忙的project同样需要 占用内存,很容易出现站着茅坑不拉屎的现象。
如果有个啥东东能像php-cgi一样监听同一端口,进行统一管理和负载平衡,那真是能省下大量的部署功夫。偶然看到了uWSGI,才发现居然一直不知道有那么方便地统一部署工具。

uWSGI,既不用wsgi协议也不用fcgi协议,而是自创了一个uwsgi的协议,据说该协议大约是fcgi协议的10倍那么快,有个比较见下图

uWSGI的主要特点如下,其中一些功能让我感动得泪流满面
  1. 超快的性能
  2. 低内存占用(实测为apache2的mod_wsgi的一半左右)
  3. 多app管理(终于不用冥思苦想下个app用哪个端口比较好了-.-)
  4. 详尽的日志功能(可以用来分析app性能和瓶颈)
  5. 高度可定制(内存大小限制,服务一定次数后重启等)
总而言之uwgi是个部署用的好东东,正如uWSGI作者所吹嘘的:
If you are searching for a simple wsgi-only server, uWSGI is not for you, but if you are building a real (production-ready) app that need to be rock-solid, fast and easy to distribute/optimize for various load-average, you will pathetically and morbidly fall in love (we hope) with uWSGI.

正式开工

uwsgi的文档虽然蛮多也很详细,但是他们网站的排版真是让人无语,粗粗看上去根本不知道文档在哪里。其实是在这里:http://projects.unbit.it/uwsgi/wiki/Doc

0.安装uwsgi

ubuntu有uwsgi的ppa
add-apt-repository ppa:stevecrozz/ppa
apt-get update
apt-get install uwsgi

1. 用uwsgi代替mod_wsgi

nginx的整体配置说来话长,我也不再罗嗦了,假设已经明白nginx的基本配置,那么uwsgi就类似这么配置:
location / {
  include uwsgi_params
  uwsgi_pass 127.0.0.1:9090
}
这就是把所有url传给9090端口的uwsgi协议程序来互动。
再到project目录建立myapp.py,使得application调用框架的wsgi接口,比如web.py就是
......
app = web.application(urls, globals())
application = app.wsgifunc()
再比如django就是
.......
from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()
然后运行uwsgi监听9090,其中-w后跟模块名,也就是刚才配置的myapp
uwsgi -s :9090 -w myapp
运行网站发现已经部署完成了。

2. uwsgi的参数

以上是单个project的最简单化部署,uwsgi还是有很多令人称赞的功能的,例如
并发4个线程
uwsgi -s :9090 -w myapp -p 4
主控制线程+4个线程
uwsgi -s :9090 -w myapp -M -p 4
执行超过30秒的client直接放弃
uwsgi -s :9090 -w myapp -M -p 4 -t 30
限制内存空间128M
uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128
服务超过10000个req自动respawn
uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128 -R 10000
后台运行等
uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128 -R 10000 -d uwsgi.log
更多用法见文档:http://projects.unbit.it/uwsgi/wiki/Doc

3.为uwsgi配置多个站点

为了让多个站点共享一个uwsgi服务,必须把uwsgi运行成虚拟站点:去掉“-w myapp”加上”–vhost”
uwsgi -s :9090 -M -p 4 -t 30 --limit-as 128 -R 10000 -d uwsgi.log --vhost
然后必须配置virtualenv,virtualenv是python的一个很有用的虚拟环境工具,这样安装
apt-get install python-setuptools
easy_install virtualenv
然后设置一个/多个app基准环境
virtualenv /var/www/myenv
应用环境,在此环境下安装的软件仅在此环境下有效
source /var/www/myenv/bin/activate
pip install django
pip install mako
...
最后配置nginx,注意每个站点必须单独占用一个server,同一server不同location定向到不同的应用不知为何总是失败,我猜也算是一个bug。
server {
        listen       80;
        server_name  app1.mydomain.com;
        location / {
                include uwsgi_params;
                uwsgi_pass 127.0.0.1:9090;
                uwsgi_param UWSGI_PYHOME /var/www/myenv;
                uwsgi_param UWSGI_SCRIPT myapp1;
                uwsgi_param UWSGI_CHDIR /var/www/myappdir1;
        }
    }
    server {
        listen       80;
        server_name  app2.mydomain.com;
        location / {
                include uwsgi_params;
                uwsgi_pass 127.0.0.1:9090;
                uwsgi_param UWSGI_PYHOME /var/www/myenv;
                uwsgi_param UWSGI_SCRIPT myapp2;
                uwsgi_param UWSGI_CHDIR /var/www/myappdir2;
        }
    }
如此这般,重启nginx服务,两个站点就可以共用一个uwsgi服务了。

4.实战应用

最初的设置完毕以后,再添加的应用,只需要在nginx里面进行少量修改,无需重启uwsgi,就能立刻部署完毕。uwsgi自带了基于django的监控uwsgi运行状态的工具,就拿它来部署好了:
server {
    listen 80;
    root   /var/www/django1.23;
    index  index.html index.htm;
    server_name uwsgiadmin.django.obmem.info;
    access_log  /var/log/nginx/django.access.log;
    location /media/ {
        root /var/www/django1.23/adminmedia;
        rewrite ^/media/(.*)$ /$1 break;
    }
    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:9090;
        uwsgi_param UWSGI_PYHOME /var/www/django1.23/vtenv;
        uwsgi_param UWSGI_CHDIR /var/www/django1.23/uwsgiadmin;
        uwsgi_param UWSGI_SCRIPT uwsgiadmin_wsgi;
    }
}
于是uwsgi的监控信息可以在http://uwsgiadmin.django.obmem.info 看到用户名密码都是admin。
再比如LBForum论坛程序的部署:根据安装说明安装完毕,再按部署说明修改完配置文件,然后只需修改nginx配置文件:
server {
    listen 80;
    root   /var/www/django1.23;
    index  index.html index.htm;
    server_name lbforum.django.obmem.info;
    access_log  /var/log/nginx/django.access.log;
    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:9090;
        uwsgi_param UWSGI_PYHOME /var/www/django1.23/vtenv;
        uwsgi_param UWSGI_CHDIR /var/www/django1.23/LBForum/sites/default;
        uwsgi_param UWSGI_SCRIPT lbforum_wsgi;
    }
}
于是 http://lbforum.django.obmem.info 就是论坛程序了。

后记

虽然写出来寥寥几行,配置的时候我可吃尽了uwsgi的苦头,有些想当然的用法完全不能成立,–no-site参数一加上去其他都好使LBForum怎么都部署不了,一开始多站点公用uwsgi怎么都成功不了等等。
python世界很有趣,一直会发现好玩的东东,但是python世界也很折腾人,大部分东东都是dev版本,文档缺失,各种兼容问题……大约是因为在python中,有个idea到实现出来实在是太过高效的关系吧,唉,被折腾死了。
from http://obmem.info/?p=703
------------------------------------------------------------------------

用Nginx+uWSGI部署django app


常见的django webapp 部署方式采用FCGIWSGI的方式部署,今天我这备忘下采用uWSGI的部署方式。 目前我这博客就是采用 Nginx + uWSGI + Python + Django 构建的,部署虽没有php那样扔到目录那么方便,但是并发和性能消耗还是非常不错的。这里不想赘述关于FCGI, WSGI,uWSGI之间的比较,网上关于这样的对比测试也有很多,例如这里这里。这里说下部署过程。 uWSGI 的官方网站 http://projects.unbit.it/uwsgi/ wiki介绍的很详细。 Nginx关于HttpUwsgiModule的介绍http://wiki.nginx.org/HttpUwsgiModule.有这些资料参考,安装部署是很容易的事情。
  • uWSGI的安装
下载uWSGI的最新版
wget http://projects.unbit.it/downloads/uwsgi-0.9.9.2.tar.gz
因为我最后采用xml配置django app 的部署,所以编译 uWSGI 时候需要把libxml编译进去
sudo apt-get install libxml2-dev
剩下的就简单了
tar zxvf uwsgi-0.9.9.2.tar.gz
cd uwsgi-0.9.9.2
make -f Makefile.Py26 #指定你python的版本,如果你的python是2.7 就应该是 make -f Makefile.Py27
cp uwsgi /usr/sbin/uwsgi
至此 uWSGI 就算是安装完成了,下一步安装 Nginx > 0.8 的版本,因为只有Nginx > 0.8 的版本才支持wsgi
  • Nginx 安装
Ubuntu 默认源里面的Nginx版本比较旧,这里需要先添加一个Nginx的源,来通过apt-get安装新版本的Nginx
sudo add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx
接下来配置Nginx 和 uWSGI部署Django App 了. 首先我们在Nginx中新建一个站点配置文件:
sudo vi /etc/nginx/sites-enabled/blog.hysia.com
内容如下:
server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    server_name blog.hysia.com;

    access_log /var/log/nginx/blog.hysia.com-access.log ;
    error_log /var/log/nginx/blog.hysia.com-error.log ;

    location / {
            uwsgi_pass 127.0.0.1:8630;
            include uwsgi_params;
    }

}
这样Nginx算是配置完了,现在看我们的Django app如何配置。
  • 配置Django app
配置很简单,几乎不用改动你app的任何文件。
首先在你的app目录创建个wsgi.py 文件,内容如下:
import os,sys

if not os.path.dirname(__file__) in sys.path[:1]:
    sys.path.insert(0, os.path.dirname(__file__))
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()
然后在app目录创建个django.xml文件,作为uWSGI运行的配置文件,内容如下:
<uwsgi>
    <socket>127.0.0.1:8630</socket>
    <chdir>/home/hysia/website/blog</chdir>
    <pythonpath>..</pythonpath>
    <module>wsgi</module>
</uwsgi>
最后一步,运行 uWSGI ,重启 Nginx 就行了,如下:
uwsgi -x /home/hysia/website/blog/django.xml &
nginx -s reload
就这样你的Django app 就用 uWSGI hold 住了。当然django.xml的配置远不止这些,比如log文件,内存限制等等,具体的大家可以参看 http://projects.unbit.it/uwsgi/wiki/Example 用uWSGI handle 多个 Django app 的时候性能更出众,更多的探索自己去动手实践吧。
from http://blog.hysia.com/post/2/nginx-uwsgi-deploy-django-apps/
-------------------------------------------------------------------------------

用uWSGI替代fastcgi部署django app

uwsgi比 fastcgi 方式快很多。
首先下载编译 uwsgi:http://projects.unbit.it/downloads/uwsgi-0.9.9.1.tar.gz,我是 ubuntu 系统,需要额外装个 libxml2-dev 库:sudo apt-get install libxml2-dev
编译完后将得到的 uwsgi 复制到系统目录:sudo cp uwsgi /usr/sbin/
启动 uwsgi:
uwsgi -s /tmp/uwsgi.sock -C -M -p 4 -t 30 --limit-as 128 -R 10000 --vhost -d /tmp/uwsgi.log --pidfile /tmp/uwsgi.pid --pythonpath /var/www
表示用 unix socket 方式执行 uwsgi,-C 表示将 /tmp/uwsgi.sock 文件权限改成 666 以便 nginx 可以读取,-M 表示启动管理进程,-p 4 表示预生成 4 个 worker 子进程,-t 30 是 cgi 程序超时,--limit-as 128 表示限制内存最大 128M,-R 10000 表示每个 worker 处理的最大请求数,--vhost 表示启用虚拟服务器,-d /tmp/uwsgi.log 表示以守护进程方式启动,指定日志文件。
这个命令可以放入 /etc/rc.local 作为开机自启动。
这样启动的 uwsgi 可以被多网站共用,nginx 的 server 块配置如下:
location / {
    uwsgi_pass  unix:///tmp/uwsgi.sock;
    uwsgi_param UWSGI_CHDIR  /var/www/djblog;
    uwsgi_param UWSGI_SCRIPT wsgi_app;
    include     uwsgi_params;
}
上面的配置的前提是,你的 django 工程在 /var/www/djblog,并且在该目录下有个 wsgi_app.py 文件。文件内容如下:
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'djblog.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
如此配置好后,重启 nginx 就可以了。
如果要多加一个网站,只需在 nginx 配置中新加个 server 块,改变下 UWSGI_CHDIR 配置即可。
如果要让 uwsgi 重新载入,可以执行:
kill -SIGHUP `cat /tmp/uwsgi.pid`
如果要让停止 uwsgi,可以给它的 master 进程发送 SIGINT 信号:
kill -SIGINT `cat /tmp/uwsgi.pid`
uwsgi 的更多配置在此.
from http://ichuan.net/post/6/using-uwsgi-instead-of-fastcgi-for-django-app/
------------------------------------------------------------------------------------
Python 2.6.5 + Django 1.2.1 + Nginx Installation &Configuration
一、install
## 万恶的XXX,封掉了python下的所有目录,首页上的download链接是打不开的,不过可以到其他的链接下载 ##
## 1、http://ftp.python.org/ftp/python/2.6.5/
## 2、http://www.python.org/ftp/python/
1. Python 2.6.5
1) install
wget http://ftp.python.org/ftp/python/2.6.5/Python-2.6.5.tgz
 
tar zxvf Python-2.6.5.tgz
cd Python-2.6.5
./configure --prefix=/opt/python26
make
make install
 
ln -s /opt/python26/bin/python2.6 /usr/bin/python26
## add the /opt/python26/bin to the PATH
vi /etc/profile
###########################
PATH=”$PATH:/opt/mysql/bin:/opt/python/bin:/opt/nginx/sbin:/opt/python26/bin”;export PATH
###########################
2)test
[root@devel photo_uw]# python26
Python 2.6.5 (r265:79063, Jul 20 2010, 10:39:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

2. PIL
1) install
wget http://effbot.org/downloads/Imaging-1.1.7.tar.gz
 
tar zxvf Imaging-1.1.7.tar.tar
cd Imaging-1.1.7
python26 setup.py build_ext -i
python26 setup.py install
cd ..
2) test
[root@devel photo_uw]# python26
Python 2.6.5 (r265:79063, Jul 20 2010, 10:39:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Image
>>>

3. setuptools
wget http://pypi.python.org/packages/source/s/setuptools/setuptools-0.6c11.tar.gz
 
tar zxvf setuptools-0.6c11.tar.gz
cd setuptools-0.6c11
python26 setup.py install
cd ..

4. flup
wget http://www.saddi.com/software/flup/dist/flup-1.0.2.tar.gz
 
tar zxvf flup-1.0.2.tar.gz
cd flup-1.0.2
python26 setup.py install
cd ..

5. MySQL-python
1) install
wget http://nchc.dl.sourceforge.net/project/mysql-python/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz
 
tar zxvf MySQL-python-1.2.3c1.tar.gz
cd MySQL-python-1.2.3c1
python26 setup.py build
python26 setup.py install
cd ..
2) test
[root@devel photo_uw]# python26
Python 2.6.5 (r265:79063, Jul 20 2010, 10:39:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MySQLdb
>>>

6 Django 1.2.1
1) install
wget http://media.djangoproject.com/releases/1.2/Django-1.2.1.tar.gz
 
tar zxvf Django-1.2.1.tar.gz
cp -R Django-1.2.1 /opt/python26
cd /opt/python26/lib/python2.6/site-packages/
ln -s /opt/python26/Django-1.2.1/django django
or
cd Django-1.2.1
python26 setup.py install
2) test
[root@devel photo_uw]# python26
Python 2.6.5 (r265:79063, Jul 20 2010, 10:39:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
'1.2.1'
7. django-treebeard
1) install
wget http://pypi.python.org/packages/source/d/django-treebeard/django-treebeard-1.61.tar.gz
 
tar zxvf django-treebeard-1.61.tar.gz
cd django-treebeard-1.61
python26 setup.py install
2) test
[root@devel photo_uw]# python26
Python 2.6.5 (r265:79063, Jul 20 2010, 10:39:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import treebeard
>>>
二. configure
1) nginx
cd /opt/nginx/conf/vhosts
 
vi vhost-www_tech.conf
 
 
 upstream backend_www_tech {
  #server unix:/var/run/fcgi/www/www_tech.sock;
  server unix:/var/run/fcgi/www_tech.sock;
 }
 
 server {
  listen       192.168.0.250;
  server_name  192.168.0.250;
 
  #charset gb2312;
 
  access_log  /var/log/nginx/www_tech/www_tech_access_log combined;
  error_log   /var/log/nginx/www_tech/www_tech_error_log notice;
 
  location / {
   root        /infoware/www_tech/web;
   #allow  all;
   #fastcgi_pass    backend_dorm;
   fastcgi_pass    backend_www_tech;
   fastcgi_param   PATH_INFO       $fastcgi_script_name;
   fastcgi_param   REMOTE_ADDR     $remote_addr;
   fastcgi_pass_header             Authorization;
   include         fastcgi_params_django;
 
  }
 
  location /static {
   root            /infoware/www_tech/web;
  }
 
  error_page  404     http://192.168.0.250/static/error404.htm;
 }
## 这里不能使用nginx默认的fastcgi_params,测试的时候发现所有的页面都会跳转到首页,而且也不报错
## 貌似是SCRIPT_NAME所引起的问题,而Django好像使用的是PATH_INFO,为了避免和其他的fcgi冲突,所以新建一个django专用的fastcgi_params_django
## Python2.4 + Django 0.96 版本不需要,因为Django 0.96 还不支持SCRIPT_NAME
## 可以查看django的django\core\handlers目录下的modpython.py 文件
vi /opt/nginx/conf/fastcgi_params_django
 
fastcgi_param  PATH_INFO          $fastcgi_script_name;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
# fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
# fastcgi_param  REQUEST_URI        $request_uri;
# fastcgi_param  DOCUMENT_URI       $document_uri;
# fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
2) fcgi
cd /infoware/_conf/www_tech/
 
vi start_www_tech.sh
 
#!/bin/bash
 
## start_www_tech.sh: start www_tech app in django fcgi mode
## ljzhou, 2010.08.26
 
## TODO
#  - executed under deamontools(in method=thread mode), to get
#    (1) controled env (2) 'web' uid (3) monitored process
#  - dormctl.sh script(nginx+django?), just as apachectl
 
APP_DIR="/infoware/www_tech/web"
CFG_DIR="/infoware/_conf/www_tech"
 
PYTHON="/usr/bin/python26"
DJANGO_ADMIN="/opt/python26/lib/python2.6/site-packages/django/bin/django-admin.py"
#PYTHON="/opt/python/bin/python2"
#DJANGO_ADMIN="/usr/lib/python2.4/site-packages/django/bin/django-admin.py"
 
############### no config below this line ##################
export PYTHONPATH="$PYTHONPATH:$CFG_DIR"
# mysettings.py in $CFG_DIR
#export DJANGO_SETTINGS_MODULE=mysettings
export DJANGO_SETTINGS_MODULE=settings
 
umask 027
 
## server: self daemonized, total num=20 with 10 threads each
## Help message:   help
## TCP socket  :   host=... port=...
PIDFILE="/var/run/fcgi/www_tech.pid"
if [ -f $PIDFILE ]; then
    kill `cat -- $PIDFILE`
    rm -f -- $PIDFILE
    sleep 3
fi
 
$PYTHON $DJANGO_ADMIN \
    runfcgi daemonize=true method=prefork \
    maxspare=5 minspare=2 maxchildren=10 maxrequests=500 \
    socket="/var/run/fcgi/www_tech.sock" pidfile=$PIDFILE \
    umask=000 debug=true \
    --pythonpath=$APP_DIR
 
# EOF: start_www_tech.sh
 
 
stop script like this , only Remark those:
 
#$PYTHON $DJANGO_ADMIN \
#    runfcgi daemonize=true method=prefork \
#    maxspare=5 minspare=2 maxchildren=10 maxrequests=500 \
#    socket=&amp;"/var/run/fcgi/www_tech.sock" pidfile=$PIDFILE \
#    umask=000 debug=true \
#    --pythonpath=$APP_DIR

from http://tech.foolpig.com/2010/08/30/python-django-nginx/
-----------------------------------------------------------------------------

使用 uWSGI + Nginx 部署 Flask app

 
一直在纠结地部署Flask+uWSGI+Nginx,也许是因为我领悟能力有问题,这个部署过程研究了整整一天,看了很多文档,其他开发人员写的
部署的博客,但是发现都写得不够好,有些细节没提及,导致走了些弯路,所以我写了这篇blog,给后面在部署Flask+uWSGI+Nginx的同学一
些帮助。
首先,我用的Flask是0.8版本的,uwsgi是0.9.9.2版,nginx是1.0版本,这个版本很重要,因为uwsgi的0.9.8版和 0.9.9.2版在command line上有些option是不同的,具体可以安装完uwsgi,在terminal里敲"wsgi -h"的帮助里看命令的option信息;nginx1.0版和nginx0.8版也有差别,nginx1.0里采用了和apache相似的sites- available和sites-enable来实现配置的virtual host组件化,而nginx0.8版里还是老风格,因为在我查资料时经常碰到别人的配置部署就OK,但在我的环境下就不行,其实一部分原因是和环境有 关。操作系统我用的是ubuntu11.10

1)安装Flask,uwsgi,nginx

Flask:sudo apt-get install python-flask
uwsgi:可以看下http://library.linode.com/web-servers/nginx/python-uwsgi/ubuntu-10.10-maverick
nginx:sudo apt-get install nginx

2)创建Flask工程

这里就用最简单的HelloWorld,创建一个工程目录:myapp,里面包含以下文件:
文件名:myapp.py
代码:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
     return 'Hello World'
if __name__ == '__main__':
       app.run()

3)配置 uwsgi

在刚才创建的myapp目录下创建一个uwsgi的xml配置文件myapp_config.xml:
<uwsgi>
     <pythonpath>[你的工程的根目录]</pythonpath>
     <module>[模块名,这里用myapp]</module>
     <callable>[因为app是启动整个服务的入口,所以是app]</callable>
     <socket>/tmp/uwsgi.sock</socket>       #注:这里的sock文件不是某个现成的文件,也不需要事先创建,运行时会自动创建,文件名也是自己定的,路径也是可以自己定的
     <master/>
     <processes>4</processes>                #注:跑几个线程,这里用4个线程
     <memory-report/>
</uwsgi>

4)配置 nginx

在/etc/nginx/sites-available/目录下,创建一个站点文件:site
server {
        listen 80;
        server_name www.myapp.com;

        location / {
                include uwsgi_params;
                uwsgi_pass unix:/tmp/uwsgi.sock;   #注:这里的sock文件和uwsgi的sock文件配的是同一个文件,因为nginx和uwsgi需要通过这个socket进行交互
        }
}
 然后用Linux的ln命令创建一个link到/etc/nginx/sites-enable/里,link的名字也叫site,删除sites-enable目录下的default的link

5)开始部署

启动uwsgi,命令是 sudo uwsgi -x myapp_config.xml,会打出很多的字,如果没有加载工 程成功可以从打出的信息中看出,然后不要关闭该Terminal,新打开一个Terminal,在里面启动nginx:sudo /etc/init.d/nginx start,然后在浏览器里访问localhost,这时如果出现502页面,可以看下日志,我的日志是在/var/log/nginx /error.log,如果里面显示是sock文件因为权限问题无法访问,那只要利用chmod命令给sock文件赋上权限:chmod 777 /tmp/uwsgi.sock,然后uwsgi和nginx再重启一下,现在访问localhost就可以看到“Hello World!”,OK!
---------------------------------------------------------------------------------------------
 
django+uwsgi on nginx
I decided to move us to a lighter application server so that we could get the most out of our system resources, and after a lot of research and testing I chose uWSGI. While I was at it, I decided to replace Perlbal and Lighttpd with Nginx because of its great configuration syntax and excellent performance. I also upgraded us to Ubuntu 10.04 and Postgres 8.4. The result was a resounding success! Memory usage and CPU load on each of the web nodes dropped dramatically. Swap usage dropped to almost nothing. The overall responsiveness of the site improved noticeably, and the timeout errors and OGR failures disappeared entirely. If you'd like to give this stack a try, read on for an overview of the setup on Ubuntu 10.04. I'm using the standard Ubuntu source package for Nginx, but modifying it slightly and them installing it with dpkg-buildpackage. This post is just about the setup relevant to Nginx and uWSGI. If you need a more complete server setup guide, try my Provisioning a new server post. uWSGI Before we build Nginx, uWSGI needs to be compiled so that its module can be included in the Nginx build. $ sudo apt-get install build-essential python-dev libxml2-dev $ wget http://projects.unbit.it/downloads/uwsgi-0.9.5.4.tar.gz $ tar -xzf uwsgi-0.9.5.4.tar.gz $ cd uwsgi-0.9.5.4 $ make -f Makefile.Py26 Copy the executable to the local sbin directory. $ sudo cp uwsgi /usr/local/sbin Also, copy the default uwsgi settings to the /etc/nginx directory. $ sudo mkdir /etc/nginx $ sudo cp nginx/uwsgi_params /etc/nginx $ cd .. Nginx We need to slightly modify the nginx package from Ubuntu to add uWSGI (and, optionally, SSL). $ sudo apt-get install libssl-dev $ sudo apt-get build-dep nginx $ apt-get source nginx $ cd nginx-0.7* $ emacs debian/rules Add the following lines to the end of the configure options. Make sure to include backslashes so that all the options are interpreted as being on one line. If you don't need SSL, ignore that line.     --with-http_ssl_module \     --add-module=$(CURDIR)/../uwsgi-0.9.5.4/nginx Build, install, and hold the packages. $ dpkg-buildpackage $ cd .. $ sudo dpkg -i nginx*.deb $ echo "nginx hold" | sudo dpkg --set-selections $ echo "nginx-dbg hold" | sudo dpkg --set-selections Starting with nginx-0.8.41, you can add something like --http-uwsgi-temp-path=/var/lib/nginx/uwsgi to the debian/rules so that the temp files are kept in the right place. Until then (probably a later version of Ubuntu), you'll need to create a /usr/local/nginx/uwsgi_temp folder to use for the temp files. $ sudo mkdir -p /usr/local/nginx/uwsgi_temp Supervisor To manage the uWSGI processes, I use Supervisor. In Ubuntu 10.04, you can simply install it with apt-get. $ sudo apt-get install supervisor Configuration Supervisor To configure uWSGI, I use command-line options in my Supervisor config. The example below is similar to what I use in production for Pegasus, but you'll want to take a look at the uWSGI docs and tweak for your situation. [program:myapp] command=/usr/local/sbin/uwsgi   --home /home/myuser/.virtualenvs/myapp/   --module myapp.deploy.wsgi   --socket 10.1.2.3:10000   --pythonpath /sites/myapp.com/code/myapp   --processes 5   --master   --harakiri 120   --max-requests 5000 directory=/sites/myapp.com/code/myapp environment=DJANGO_SETTINGS_MODULE='myapp.settings' user=www-data autostart=true autorestart=true stdout_logfile=/sites/myapp.com/logs/uwsgi.log redirect_stderr=true stopsignal=QUIT The module I specify in the --module option simply contains: import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() The IP address in the --socket option is the server's IP address on the interface reserved for local network traffic. On Rackspace, eth1 is your local interface. Use the ifconfig command to find your IP address on the local interface. If you're just using uWSGI on localhost, you can use something like --socket /sites/myapp.com/var/run/myapp.sock instead to avoid the overhead of the full TCP stack. My value for --harakiri is rather high, and my value for --max-requests is rather low. You may not even need either of these options, but I'm using them to solve some problems specific to Pegasus. Nginx For the site-specific Nginx config, I'm using something like this:    upstream myapp {     server 10.1.2.3:10000;     server 10.1.2.4:10000;     server 10.1.2.5:10000; } server {     listen 80;     listen 443;     server_name myapp.com www.myapp.com;     access_log /sites/myapp.com/logs/nginx-access.log;     error_log /sites/myapp.com/logs/nginx-error.log;     root /sites/myapp.com/public;     ssl_certificate /sites/myapp.com/ssl/myapp.crt;     ssl_certificate_key /sites/myapp.com/ssl/myapp.key;     location / {         # This checks for a file called simply "downtime" in the public         # directory, and puts up the downtime page if it exists.         if (-f /sites/myapp.com/public/downtime) {             return 503;         }         uwsgi_pass myapp;         include uwsgi_params;     }     location /media {         # This makes static media available at the /media/ url.  The         # media will continue to be available during site downtime,         # allowing you to use styles and images in your maintenance page.         alias /sites/myapp.com/public/media;     }     error_page 502 503 504 @maintenance;     location @maintenance {         # In this example, there's a directory in the site media files         # called "downtime" that contains a "maintenance.html" file and         # any styles and images needed for the maintenance page.         root /sites/myapp.com/public/media/downtime;         rewrite ^(.*)$ /maintenance.html break;        } } If you're just using uWSGI on localhost, then skip the upstream section and use something like uwsgi_pass unix:///sites/myapp.com/var/run/myapp.sock; in the root location definition instead. Firing it up Restart Supervisor with sudo /etc/init.d/supervisor restart, and it should reload the config and bring the uWSGI processes up. Restart Nginx with sudo /etc/init.d/nginx restart, and you should now be able to reach your site. If not, take a look at the logs and start troubleshooting. from http://brandonkonkle.com/blog/2010/sep/14/django-uwsgi-and-nginx/ ---------------------------------------------------------------------------------------

Provisioning a new Ubuntu server for Django

I've been a long-time satisfied user of Webfaction, but recently I've had a strong urge to move to VPS hosting so that I can have greater control over the environment. After some research, I went with Rackspace Cloud because of the incredibly cheap low-end options. My site doesn't use a huge amount of bandwidth, so Rackspace looks to be the most feature-packed and still cost-effective option. A friend of mine, Kevin Whitaker, recently posted a great article about getting up and running with Django in a server environment for testing or production. He used Ubuntu, Postgres, Nginx, and FastCGI to make up his stack. I've never set up Nginx before, so his post was a great help in getting Nginx configured. My stack is slightly different, however, since I prefer to use Gunicorn instead of FastCGI and I use supervisord to manage my processes. I also use virtualenv to manage dependencies like Django itself and psycopg2. I'm including my install notes below so that I can provide a complete picture of one way of provisioning a new server from build to deploy. My site is relatively low-traffic, so I'm not going to go into postgres tweaking, connection pooling, caching, etc. I'll save those topics for another post. These notes were made on a Rackspace Cloud instance, but they should apply to a variety of other VPS hosts with only minor modifications. If you've got tips on things that need to be changed for other providers, let me know and I'll edit the post. I want this to stay up to date for awhile.

After the build is complete

Configuration

My first step was to log into my new instance using SSH. You should get an email from Rackspace with the IP address and root password.
$ ssh root@123.45.67.890

root@123.45.67.890's password:

Welcome to Ubuntu!
I then installed my preferred editor - obviously an optional step.
$ apt-get install emacs23-nox
$ export EDITOR=emacs
Then I used visudo to set up sudo access the way I like it.
$ visudo
Under this line:
Defaults        env_reset
I added the following lines to preserve my editor and Django environment settings:
Defaults        env_keep += "EDITOR VISUAL"
Defaults        env_keep += "DJANGO_SETTINGS_MODULE PYTHONPATH"
Then I changed this line:
%sudo   ALL=(ALL) ALL
To:
%admin  ALL=(ALL) ALL
This allows users with the group admin to use sudo for all commands. Then I added my first user and group. I typically prefer to use a separate user account for each developer or administrator that will be accessing the box, and add them to appropriate groups for access.
$ adduser myuser
$ addgroup admin
$ adduser myuser admin
Then I switched to my new user, and added my public key so that I can SSH without requiring a password. If you're not familiar with this, the guide at Github is quick and to the point.
$ su - myuser
$ mkdir .ssh
$ cd .ssh
$ wget http://mydomain.com/path/to/my/pubkey/id_rsa.pub
$ mv id_rsa.pub authorized_keys
Then, I logged out and made sure I can SSH in using the new user with no problems. Once that's done, I locked down the root account for security (probably because I'm a long time Ubuntu user and it just feels wrong any other way).
$ sudo passwd -l root
I also make my editor choice permanent.
$ sudo update-alternatives --config editor

Nginx

With that taken care of, I was ready to install Nginx.
$ sudo apt-get install nginx
$ sudo /etc/init.d/nginx start
$ sudo emacs /etc/nginx/nginx.conf
I used this Slicehost article to learn about the basic nginx conf options.

Postgres

Then I installed postgres. I first changed the password on the postgres user for security.
$ sudo apt-get install postgresql
$ sudo passwd postgres
$ sudo -u postgres psql

postgres=# \password postgres
postgres=# \q
Then I set up a new user to use for my site.
$ sudo -u postgres createuser myproject
$ sudo -u postgres psql

postgres=# \password myproject
postgres=# \q
I use a Unix domain socket for my postgres connection, so I have to edit pg_hba.conf to allow md5 login from domain sockets.
$ sudo emacs /etc/postgresql/8.4/main/pg_hba.conf
I change the lines that say:
# "local" is for Unix domain socket connections only                                                
local   all         all                               ident
To:
# "local" is for Unix domain socket connections only                                                
local   all         all                               md5
Then:
$ sudo /etc/init.d/postgresql-8.4 restart

(Substitute your favorite VCS here)

Now for my VCS. I use the Git PPA.
$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:git-core/ppa
$ sudo apt-get update
$ sudo apt-get install git-core

Setting up a Django site

Setting up the structure

First, I pulled over my git repositories. I use the /code directory for hosting the master copies of my repositories to use as a hub. I keep the live checkouts in /sites/mydomain.com/code/.
$ sudo mkdir /code
$ sudo chown myuser:admin /code
$ cd /code
$ git clone --mirror olddomain.com:/code/repository_name.git

$ sudo mkdir /sites
$ sudo chown myuser:admin /sites
$ cd /sites
$ mkdir -p mydomain.com/{code,public,logs,backup}
$ cd mydomain.com
$ sudo chown :www-data logs public
$ sudo chmod g+w logs public
$ git clone /code/repository_name.git code/

Initialized empty Git repository in /sites/mydomain.com/code/.git/

Media

I set up the media and made sure www-data could access it and write to the root directory.
$ cd public
$ ln -s ../code/projectname/media
$ sudo chown :www-data media
$ sudo chmod g+w media
Then I synced the media from my old server, so that user-created media wouldn't be lost.
$ rsync -avz --progress old.domain.com:~/path/to/media/ media/

Restoring the database

The next step was backing up and restoring the database.
$ ssh old.domain.com
$ pg_dump dbname | bzip2 > dbname.`date +%Y%m%dT%H%M%S`.sql.bz2
$ exit
$ ssh new.domain.com
$ cd /sites/mydomain.com/backup/
$ scp old.domain.com:~/dnmame.<timestamp>.sql.bz2 ./
$ sudo su postgres
$ createdb dbname
$ bzcat dnmame.<timestamp>.sql.bz2 | psql dbname
$ psql dbname

postgres=# GRANT ALL ON DATABASE dbname TO myproject;
postgres=# \q

$ exit

Installing dependencies

I then created my virtualenv and installed my dependencies.
$ sudo apt-get install build-essential python-dev libpq-dev
$ sudo apt-get install python-setuptools
$ sudo easy_install -U pip
$ sudo pip install virtualenv
$ sudo pip install virtualenvwrapper
$ mkdir /sites/.virtualenvs
$ emacs ~/.bashrc
At the bottom of .bashrc:
export WORKON_HOME=/sites/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
Then, back in the shell:
$ . ~/.bashrc
$ mkvirtualenv projectname
$ workon projectname
$ pip install -r /sites/mydomain.com/code/requirements.txt
$ deactivate
PIL is a tough one. I usually just install it globally. Since I install my virtualenv's with --no-site-packages, I need to symlink PIL into the site-packages.
$ sudo apt-get install python-imaging
$ workon projectname
$ cdsitepackages
$ ln -s /usr/lib/python2.6/dist-packages/PIL
$ ln -s /usr/lib/python2.6/dist-packages/PIL.pth
Then, I edited my project's settings.py to reflect the new environment setup. Finally, I added ntpdate to keep my server-s clock in sync.
$ sudo dpkg-reconfigure tzdata
$ sudo apt-get install ntpdate
$ sudo crontab -e

30 23 * * * /usr/sbin/ntpdate ntp.ubuntu.com > /dev/null

Nginx

I added an nginx.conf to my source control.
$ emacs /sites/mydomain.com/code/deploy/nginx.conf
The Nginx conf:
server {
  listen 80;
  server_name www.mydomain.com;
  rewrite ^/(.*) http://mydomain.com/$1 permanent;
}

server {
  listen 80;
  server_name mydomain.com;

  access_log /sites/mydomain.com/logs/access.log;
  error_log /sites/mydomain.com/logs/error.log;

  location /media {
    root /sites/mydomain.com/public;
  }

  location / {
    proxy_pass http://127.0.0.1:29000;
  }
}
I then symlinked it into /etc/nginx/sites-available/ and sites-enabled/.
$ sudo ln -s /sites/mydomain.com/code/deploy/nginx.conf /etc/nginx/sites-available/mydomain.com
$ sudo ln -s /etc/nginx/sites-available/mydomain.com /etc/nginx/sites-enabled/mydomain.com
$ sudo /etc/init.d/nginx restart

Gunicorn

Gunicorn should be installed in your virtualenv as part of your requirements.txt. If you're not using virtualenv and pip, or zc.buildout, then you should definitely read up on them. They are a vital part of any serious Django stack.
$ emacs /sites/mydomain.com/code/deploy/gunicorn.conf.py
I already had a simple Gunicorn conf in my source control, which I simply modified for the new environment.
bind = "127.0.0.1:29000"
logfile = "/sites/mydomain.com/logs/gunicorn.log"
workers = 3

Supervisord

$ sudo pip install supervisor
$ sudo emacs /etc/supervisord.conf
Here's a basic config file:
[unix_http_server]
file=/tmp/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB       ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10          ; (num of main logfile rotation backups;default 10)
loglevel=info               ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false              ; (start in foreground if true;default false)
minfds=1024                 ; (min. avail startup file descriptors;default 1024)
minprocs=200                ; (min. avail process descriptors;default 200)

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

[program:myproject]
command=/sites/.virtualenvs/myproject/bin/gunicorn_django -c deploy/gunicorn.conf.py
directory=/sites/mydomain.com/code
user=www-data
autostart=true
autorestart=true
stdout_logfile=/sites/mydomain.com/logs/supervisord.log
redirect_stderr=true
Then I created an init.d script:
$ sudo emacs /etc/init.d/supervisord
Here's what I used:
# Supervisord auto-start
#
# description: Auto-starts supervisord
# processname: supervisord
# pidfile: /var/run/supervisord.pid

SUPERVISORD=/usr/local/bin/supervisord
SUPERVISORCTL=/usr/local/bin/supervisorctl

case $1 in
start)
        echo -n "Starting supervisord: "
        $SUPERVISORD
        echo
        ;;
stop)
        echo -n "Stopping supervisord: "
        $SUPERVISORCTL shutdown
        echo
        ;;
restart)
        echo -n "Stopping supervisord: "
        $SUPERVISORCTL shutdown
        echo
        echo -n "Starting supervisord: "
        $SUPERVISORD
        echo
        ;;
esac
Then I finished up the init.d script.
$ sudo chmod +x /etc/init.d/supervisord
$ sudo update-rc.d supervisord defaults
$ sudo /etc/init.d/supervisord start
If all goes well, you can check the status on your site.
$ sudo supervisorctl status

myproject                    RUNNING    pid 11616, uptime 0:00:03
You can also grep for the gunicorn processes.
$ ps -ef | grep gunicorn

Testing

To test this new setup, you can add domain name overrides to the /etc/hosts file on your local machine.
# Do this on your local machine - not your server
$ sudo emacs /etc/hosts

123.45.67.890 mydomain.com
Now you can go to your browser and access mydomain.com. You should see your site. To restart your site, use:
$ sudo supervisorctl restart myproject
Make sure to change your /etc/hosts back. from http://brandonkonkle.com/blog/2010/jun/25/provisioning-new-ubuntu-server-django/
 --------------------------------------------------------------------------------------------
 uwsgi的多站点配置

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.urdomain.com的配置为:

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

        access_log /srv/logs/access-www.urdomain.com.log;
        error_log /srv/logs/error-www.urdomain.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.urdomain.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.urdomain.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.urdomain.com/py')

from app import application

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

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

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

最后,重启uwsgi和nginx生效.
----------------------------------------------------------------------
 基于Nginx+uWsgi的Django一键部署脚本

 在Nginx上使用uWsgi代替FastCGI运行Django不仅性能可以提高数倍,而且还可以具有低内存占用,部署简便等诸多优点。

为了方便在服务器上部署Nginx+uWsgi,我写了个一键部署脚本,在CentOS 6.2上已经成功安装,其他平台目前尚未测试。

注意:在使用此脚本之前需要先安装Nginx,Nginx的安装方法可以自行Google,在此不再赘述。
Django+uWsgi一键安装脚本

下载脚本https://github.com/chon219/Code/blob/master/scripts/uwsgi-install.sh

执行 chmod +x uwsgi-install.sh 给该脚本赋予可执行权限

然后以root身份执行脚本 ./uwsgi-install.sh

根据提示输入网站的根目录路径,比如/home/wwwroot 即可开始安装。

安装完成后,uwsgi服务将会自动添加到系统启动项中,毋须手动添加
管理uWsgi服务

启动uWsgi: /etc/init.d/uwsgi start   停止uWsgi: /etc/init.d/uwsgi stop   重启uWsgi: /etc/init.d/uwsgi restart

注意:每次修改Django应用之后,都需要重启uWsgi服务使新的应用生效。
添加多个Django应用

下载uWsgi-app脚本https://github.com/chon219/Code/blob/master/scripts/uwsgi-app.sh

执行 chmod +x uwsgi-app.sh 给该脚本赋予可执行权限

然后以root身份执行脚本 ./uwsgi-app.sh 根据提示输入域名和Django应用名称,即可自动添加Django应用。

注意:默认情况下,新添加的Django应用位于网站根目录的同名目录。比如网站根目录为/home/wwwroot,Django应用为test,则该应用的目录为/home/wwwroot/test。

默认设定:

网站根目录默认为/home/wwwroot,由变量$webroot指定;

Nginx的vhost配置文件目录默认为/usr/local/nginx/conf/vhost,由变量$nginxvhost指定.
 ------------------------------------------------------------------------------------------

使用NGINX+UWSGI来部署Django

关于UWSGI的介绍不多说了,想了解的可以自己去搜,uwsgi性能还蛮不错,我们之前使用的fastcgi方式来跑django,前端用F5做负载均衡,用户数增加后服务器的load很高,但换uwsgi服务器的load下降不少,废话不多说,进入正题。
编译安装nginx,用的nginx-0.8.54,目前最新的stable版本
#wget http://nginx.org/download/nginx-0.8.54.tar.gz #tar zxvf nginx-0.8.54.tar.gz #./configure --user=nobody --group=nobody --prefix=/usr/local/nginx --with-http_ssl_module --http-log-path=/var/log/nginx/access.log --with-http_gzip_static_module #make&&make install
下面来安装uwsgi
#wget http://projects.unbit.it/downloads/uwsgi-0.9.6.5.tar.gz #tar zvxf uwsgi-0.9.6.5.tar.gz #cd uwsgi-0.9.6.5 #make -f Makefile.Py26 #cp uwsgi /usr/sbin/uwsgi #将uwsgi放到PATH下
下面来说说怎么配置:
新建一个uwsgi.xml的文件放到django的目录下
#cat uwsgi.xml
<uwsgi>
<socket>0.0.0.0:8000</socket>
<listen>204800</listen>
<processes>32</processes> #开启32个线程
<max-requests>2048000</max-requests>
<buffer-size>8192</buffer-size>
<module>django_wsgi</module> #你的配置文件
<profiler>true</profiler>
<enable-threads>true</enable-threads>
<limit-as>256</limit-as> #限制内存空间256M
<async>10</async> #使用async模式来运行,这里要注意一下,
如果你的app的是no-async-friendly 那就不要用这个模式 <disable-logging/>
<daemonize>/home/app01/uwsgi.log</daemonize>
</uwsgi>
#cat django_wsgi.py import os import django.core.handlers.wsgi os.environ['DJANGO_SETTINGS_MODULE'] = 'your settings' application = django.core.handlers.wsgi.WSGIHandler()
下面是nginx的配置:
server { listen 80; server_name jasonwu.me; access_log /var/log/jasownu.me/access_log; location / { root /home/app01/ uwsgi_pass 127.0.0.1:8000; include uwsgi_params; } }
启动服务:
#/usr/bin/uwsgi -x /home/app01/uwsgi.xml
#/usr/local/nginx/sbin/nginx
这样部署完成了
下面来说说遇到的一个问题,不知道大家有没有遇到过,
在我们启动uwsgi后在uwsgi的日志中会出现如下的信息:
– unavailable modifier requested: 1 –
– unavailable modifier requested: 1 –
表现的现象就是启动一段时间没法访问app,在查看uwsgi的源代码中我们找到打印这部份日志的段落,正常情况下应该返回的-1,目前还在查找这个出现这个错误的原因。