首先先说一下,PyCon官网使用了Uliweb做为Web Framework,Tornado通过WSGI提供Web Server服务,所以Tornado的守护进程重要性就不言而喻了。我们知道,Tornado的守护进程无法监测自己的运行状态,如果守护进程异常退出 (虽然这种情况并不常见),Web服务就会直接停止,而这,正是我们需要避免的。
首先,我们先安装Supervisor,Supervisor是一个用Python写成的程序,它通过守护进程来启动并监测子进程的运行。
首先确定自己处于root账户下
dndx@vps:~$ sudo su
然后安装Supervisorroot@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模式来运行,原因很简单:- 就像tornado作者在官方邮件列表中说的那样,我们不推荐你使用multiprocess模式来运行tornado,最重要的一个原因就是 tornado本身没有进程管理的能力,使用multiprocess模式如果一个子进程异常退出,父进程将没有办法捕捉到。如果父进程异常退出,那么整 个tornado服务器都会瘫痪(tornado的子进程是通过父进程向外通信的)
- 根据我在实际使用中的测试,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.