其實反向代理模式很簡單,Nginx監聽在80端口,作爲Web服務端口,而Tornado的Web服務進程監聽在808*的內部端口(能夠啓動多個進程),使用supervisor對Nginx、Tornado服務進程進行統一的管理。nginx
首先看supervisor的配置:web
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
.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
|
啓動腳本(能夠放到start.sh中):bash
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*端口上):app
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
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()
|