Total Pageviews

Monday, 11 March 2013

Tornado + Supervisor 在生产环境下的部署方法


大家都知道,Tornado 与其它的 Web Framework 比起来,最大的特点就是内置了采用了 epoll 的高性能的Web服务器。那么在实际生产过程中,Tornado 应该怎样来部署呢?我们用一个真实的案例,PyCon China 2011 官网的部署来给大家说明。
首先先说一下,PyCon官网使用了Uliweb做为Web Framework,Tornado通过WSGI提供Web Server服务,所以Tornado的守护进程重要性就不言而喻了。我们知道,Tornado的守护进程无法监测自己的运行状态,如果守护进程异常退出 (虽然这种情况并不常见),Web服务就会直接停止,而这,正是我们需要避免的。
首先,我们先安装Supervisor,Supervisor是一个用Python写成的程序,它通过守护进程来启动并监测子进程的运行。
首先确定自己处于root账户下
dndx@vps:~$ sudo su
然后安装Supervisor
root@vps:/tmp# easy_install supervisor
安装完毕后,建立Supervisor的配置文件
root@vps:/tmp# vim /etc/supervisord.conf
输入以下内容
[unix_http_server]
file=/tmp/supervisor.sock   ; (the path to the socket file)[supervisord]
logfile=/tmp/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=/tmp/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
继续编辑,输入tornado进程的信息(请自行修改,以符合你的实际需求)
[program:tornado_poll]
command=python /usr/www/PyConCN/tornado_wrapper.py --port=80%(process_num)02d              ; 要执行的命令,这里的“%(process_num)02d”会用2位精度的进程号替换,例如,第一个进程是8001,第二个进程是8002,以此类推,下同。
process_name=%(program_name)s-80%(process_num)02d   ; process_name expr (default %(program_name)s)      ;启动的进程的名字,这里的名字只是supervisor内部是别用,与你所启动程序的进程名无关
numprocs=2                   ; 启动几个tornado进程
directory=/usr/www/PyConCN/                ; 运行前cd到此目录
autostart=true                ; supervisord守护程序启动时自动启动tornado
autorestart=true              ; supervisord守护程序重启时自动重启tornado
user=www-data                   ; 运行程序前su到此用户
redirect_stderr=true          ; 将stderr重定向到stdout
stdout_logfile=/usr/www/PyConCN/logs/python_log        ; 记录控制台输出的日志位置
我们注意到上面运行了一个脚本 /usr/www/PyConCN/tornado_wrapper.py ,后面跟上参数 --port=XXXX 来指定端口,这个脚本本文后面会提供。有的人可能会问,为什么我们不采用tornado的multiprocess模式来运行,原因很简单:
  1. 就像tornado作者在官方邮件列表中说的那样,我们不推荐你使用multiprocess模式来运行tornado,最重要的一个原因就是 tornado本身没有进程管理的能力,使用multiprocess模式如果一个子进程异常退出,父进程将没有办法捕捉到。如果父进程异常退出,那么整 个tornado服务器都会瘫痪(tornado的子进程是通过父进程向外通信的)
  2. 根据我在实际使用中的测试,tornado的multiprocess模式给两个子进程分配的任务数量似乎不均等(根据CPU Time),这样可能会在高负载情况下出现不稳定的问题
当我们配置好这一切后,运行:
root@vps:/tmp# supervisord
查看supervisord和tornado的运行情况:
root@vps:/tmp# ps aux

www 11347  0.0  3.7  62440 19700 ?        S    23:13   0:00 python /usr/www/PyConCN/tornado_wrapper.py --port=8001
www 11352  0.0  3.6  62184 19308 ?        S    23:13   0:00 python /usr/www/PyConCN/tornado_wrapper.py --port=8000
root     11534  0.0  2.1  47996 11388 ?        Ss   14:44   0:01 /usr/bin/python /usr/local/bin/supervisord
这样就OK了。
supervisor自带了一个简单的后台进程控制工具,下面介绍一下使用方法
root@vps:/tmp# supervisorctl
tornado_poll:tornado_poll-8000   RUNNING    pid 11352, uptime 0:29:01
tornado_poll:tornado_poll-8001   RUNNING    pid 11347, uptime 0:29:02
supervisor>#这里可以输入控制命令
我们可以看到,上面显示了现在正在运行的守护进程的信息,下面介绍几个常用的控制命令
stop all #停止所有进程
stop tornado_poll:tornado_poll-8000 #停止运行在8000端口上的Tornado守护进程
stop tornado_poll:* #停止所有Tornado守护进程
其它的命令如 restart start 与 stop 的用法完全一样,在此就不多说了。
另,在实质使用时,需要在Tornado的前面再包一层反向代理来做负载均衡和提供静态文件,这个就相当简单了,网上一搜到处都是,官方文档的Overview里也详细介绍了用Nginx做负载均衡的方法,在此我就不废话了。
效果:运行十分稳定,两个进程的CPU Time几乎一致,Nginx也没有出现任何报错情况,完全可以在生产环境下使用.


Why Tornado and not Django?
It is really important to me to use a lightweight web server or I would have used Django.
  • Simplicity - easy to dig into the source and find out whats going on.
  • Template simplicity - I like how easy it is to test templates in the terminal or wherever.
  • No Wsgi or Factcgi - I can run Tornado directly without wsgi.