其实反向代理模式很简单,Nginx监听在80端口,做为Web服务端口,而Tornado的Web服务进程监听在808*的内部端口(可以启动多个进程),使用supervisor对Nginx、Tornado服务进程进行统一的管理。
首先看supervisor的配置:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# supervisor自己的配置及日志切割等[supervisord]logfile = /opt/logs/supervisord.loglogfile_maxbytes = 200MBlogfile_backups=10loglevel = warnpidfile = /opt/logs/supervisord.pidnodaemon = falseminfds = 1024minprocs = 200umask = 022identifier = supervisordirectory = %(here)snocleanup = truestrip_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)01dprocess_name = 808%(process_num)01dnumprocs = 4numprocs_start = 1autostart = trueautorestart = trueredirect_stderr = truestdout_logfile = /opt/logs/stdout.logstderr_logfile = /opt/logs/stdout.log# Nginx的管理配置[program:Nginx]command = /opt/sbin/nginx -c %(here)s/nginx.confprocess_name = Nginxnumprocs = 1autostart = trueautorestart = trueredirect_stderr = truestdout_logfile = /opt/logs/nginx_stdout.logstderr_logfile = /opt/logs/nginx_stdout.log |
启动脚本(可以放到start.sh中):
|
1
|
/opt/bin/supervisord /opt/conf/supervisor.conf |
重启脚本(可以放到restart.sh中)
|
1
2
3
4
5
6
7
8
|
#逐个启动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的部分配置(启动4个服务进程,监听在80端口,并反向代理负载到Tornado的808*端口上):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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; } }} |
现在Nginx已经反向代理到Tornado的服务进程监听的端口了,那么MyWeb的服务进程如何构建、并如何优雅的重启呢,略过其他代码,介绍一下主进程采用信号停止服务,并重新启动的方法。主进程的启动参数会指定此进程监听的端口,这样supervisor检测到服务进程结束后,会自动启动对应的服务进程。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
import signalimport tornado.ioloopimport tornado.httpserverhttp_server = Nonedef 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() |