django+tornado

Django的部署方式有很多种:WSGI,FastCGI等等,当然最主流的还是WSGI。比如官方文档中推荐的django+apache+mod_wsgi, django+gunicorn,django+uWSGI等等。那么什么是WSGI?

其实这个问题也困扰了我很久。每当我想研究一下WSGI到底是何方神圣的时候,google给出的答案就是pep 3333,不过这篇像论文一样的pep 3333比较晦涩难懂,一直都没搞明白。直到后来发现了这篇文章。和其他的文章不一样,文章没有开头就讲WSGI是什么,反而开始就说WSGI不是什么:

What WSGI is not: a server, a python module, a framework, an API or any kind of software. What it is: an interface specification by which server and application communicate.

看到这里心中无比的敞亮,原来WSGI就是一种标准:application和server之间交互的标准。application就是通常所说的framework,server则接受客户端的请求并将请求发给application处理,然后将application的应答返回给客户端。现在应该明白,之前说的apache+mod_wsgi, gunicorn, uWSGI都是扮演WSGI Server的角色,只要兼容WSGI的server都可以用来和任意的python web framework搭配。

今天的主角是Tornado。它包含两部分:一个framework和一个server。由于tornado使用了异步非阻塞的IO模型,所以特别适用于长轮询的场景,性能比较强大。今天主要用tornado的http server来部署django应用。

tornado的wsgi模块包含了两个类WSGIApplication和WSGIContainer。WSGIApplication是把tornado作为framework,用其他的WSGI server来驱动。WSGIContainer则是我们需要的,把其他web framework的应用封装一下,以便在tornado server上运行。

下面开始动手,将我们的django应用封装成tornado的。
[ccb_python]
#!/usr/bin/env python

tornado_main.py

import argparse
import os
os.environ.setdefault(“DJANGO_SETTINGS_MODULE”, “wordejavu.settings”)
from django.core.wsgi import get_wsgi_application

from tornado.options import options, define, parse_command_line
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.wsgi

define(‘port’, type=int, default=8080)

def main():
application = get_wsgi_application()
parse_command_line()

if name == ‘main‘:
main()
[/ccb_python]
然后修改环境变量
[ccb_bash]
export PYTHONPATH=/home/jxq/code/wordejavu/
export DJANGO_SETTINGS_MODULE=wordejavu.settings
[/ccb_bash]
现在已经可以运行tornado_main.py了。
[ccb_bash]
$ pwd
/home/jxq/code/wordejavu
$ ./wordejavu/tornado_main.py
[/ccb_bash]
不过现在还有几个问题:第一,静态文件应该由http server处理,而不是web framework处理;第二,tornado进程没有监控,如果进程挂了服务就会中断;第三,单进程性能太差。为了解决这几个问题,我们还需要nginx和supervisord。

nginx都比较熟悉,高性能的web server。supervisord是一个监控和管理进程的系统。其实上面的问题都很容易解决:第一,静态文件由nginx直接处理;第二,supervisord会负责监控tornado进程,如果进程挂了supervisord会马上起一个新的;第三,可以同时起多个tornado进程,并让nginx进行负载均衡,将请求均匀的发给多个tornado进程。

nginx配置:
[cc noborder=”true”]
http {
include mime.types;
default_type application/octet-stream;

}
[/cc]
supervisord配置,在默认的配置后面加上如下内容:
[cc noborder=”true” lang=”ini”]
[program:tornado-8080]
command=/home/jxq/code/wordejavu/wordejavu/tornado_main.py –port=8080
environment=PYTHONPATH=/home/jxq/code/wordejavu/,DJANGO_SETTINGS_MODULE=wordejavu.settings
stderr_logfile = /var/log/supervisord/tornado-stderr.log
stdout_logfile = /var/log/supervisord/tornado-stdout.log

[program:tornado-8081]
command=/home/jxq/code/wordejavu/wordejavu/tornado_main.py –port=8081
environment=PYTHONPATH=/home/jxq/code/wordejavu/,DJANGO_SETTINGS_MODULE=wordejavu.settings
stderr_logfile = /var/log/supervisord/tornado-stderr.log
stdout_logfile = /var/log/supervisord/tornado-stdout.log

[program:tornado-8082]
command=/home/jxq/code/wordejavu/wordejavu/tornado_main.py –port=8082
environment=PYTHONPATH=/home/jxq/code/wordejavu/,DJANGO_SETTINGS_MODULE=wordejavu.settings
stderr_logfile = /var/log/supervisord/tornado-stderr.log
stdout_logfile = /var/log/supervisord/tornado-stdout.log

[program:tornado-8083]
command=/home/jxq/code/wordejavu/wordejavu/tornado_main.py –port=8083
environment=PYTHONPATH=/home/jxq/code/wordejavu/,DJANGO_SETTINGS_MODULE=wordejavu.settings
stderr_logfile = /var/log/supervisord/tornado-stderr.log
stdout_logfile = /var/log/supervisord/tornado-stdout.log
[/cc]

发表评论

电子邮件地址不会被公开。 必填项已用*标注