生產環境優雅的重啓基於Nginx、Tornado的Web服務進程

Nginx是一個高效的Web服務器及代理服務器,Tornado是一個基於epoll的異步Web開發框架,一般使用Nginx作爲Web服務器時,都會以FastCGI模式,而咱們從開發、調試、運維的角度考慮,使用了反向代理的模式,同時Nginx能夠作一些特殊業務和負載均衡的處理。python

其實反向代理模式很簡單,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()
相關文章
相關標籤/搜索