Nginx is an efficient Web server and proxy server, Tornado is a Epoll-based asynchronous Web development framework, usually using Nginx as a Web server, will be in fastcgi mode, and we from the perspective of development, debugging, operation and consideration , using the reverse proxy mode, while Nginx can do some special business and load balancing processing.
In fact, the reverse proxy mode is very simple, nginx listening on the 80 port, as a Web service port, and Tornado Web service process listens on the internal port of 808* (can start multiple processes), using supervisor to Nginx, The Tornado service process is managed uniformly.
First look at the configuration of supervisor:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
# supervisor自己的配置及日志切割等
[supervisord]
logfile =
/opt/logs/supervisord
.log
logfile_maxbytes = 200MB
logfile_backups=10
loglevel = warn
pidfile =
/opt/logs/supervisord
.pid
nodaemon =
false
minfds = 1024
minprocs = 200
umask = 022
identifier = supervisor
directory = %(here)s
nocleanup =
true
strip_ansi =
false
[unix_http_server]
file =
/opt/logs/supervisord
.sock
[supervisorctl]
serverurl = unix:
///opt/logs/supervisord
.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
# 服务进程的启动及多端口
[program:MyWeb]
command =
/opt/bin/python %(here)s
/server
.py --port=808%(process_num)01d
process_name = 808%(process_num)01d
numprocs = 4
numprocs_start = 1
autostart =
true
autorestart =
true
redirect_stderr =
true
stdout_logfile =
/opt/logs/stdout
.log
stderr_logfile =
/opt/logs/stdout
.log
# Nginx的管理配置
[program:Nginx]
command =
/opt/sbin/nginx -c %(here)s
/nginx
.conf
process_name = Nginx
numprocs = 1
autostart =
true
autorestart =
true
redirect_stderr =
true
stdout_logfile =
/opt/logs/nginx_stdout
.log
stderr_logfile =
/opt/logs/nginx_stdout
.log
|
Startup script (can be placed in start.sh):
1 |
/opt/bin/supervisord /opt/conf/supervisor .conf |
Restart script (can be placed in restart.sh)
12345678 |
#逐个启动MyWeb每个端口进程,不中断服务 for i in "8081 8082 8083 8084" : do /opt/bin/supervisorctl /opt/conf/supervisor .conf restart MyWeb:$i; done #重新加载nginx的配置 /opt/sbin/nginx /opt/conf/nginx .conf -s reload; |
Nginx Partial configuration (start 4 service processes, listen on 80 ports, and reverse proxy load to Tornado's 808* port):
123456789101112131415161718192021222324 |
worker_processes 4;
daemon off;
#nginx不能以daemon模式启动
user nobody;
http {
upstream myweb {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
server 127.0.0.1:8084;
}
server {
listen 80;
server_name localhost;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_read_timeout 300s;
proxy_pass http:
//myweb
;
}
}
}
|
Now Nginx has the reverse proxy to Tornado's service process to listen to the port, then myweb how to build the service process, and how to gracefully restart it, skip the other code, introduce the main process to use the signal to stop the service, and restart the method. The startup parameters of the main process specify the ports that this process listens on, so that the corresponding service process is started automatically when the supervisor detects that the service process is finished.
1234567891011121314151617181920212223242526272829303132333435363738394041 |
import signal
import tornado.ioloop
import tornado.httpserver
http_server
= None
def sig_handler(sig, frame):
"""信号处理函数
"""
tornado.ioloop.IOLoop.instance().add_callback(shutdown) def shutdown():
"""进程关闭处理
"""
# 停止接受Client连接
global http_server
http_server.stop()
io_loop
= tornado.ioloop.IOLoop.instance()
deadline
= time.time()
+ 10 #设置最长强制结束时间
def stop_loop():
now
= time.time()
if now < deadline:
io_loop.add_timeout(now
+ 1
, stop_loop)
else
:
io_loop.stop()
stop_loop()
if __name__
=
= ‘__main__‘
:
# 等待supervisor发送进程结束信号
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
app
= Application()
http_server
= tornado.httpserver.HTTPServer(app, xheaders
=
True
)
http_server.listen(tornado.options.options.port)
tornado.ioloop.IOLoop.instance().start()
|
Graceful restart of production environment based on Nginx, Tornado Web service process