生產環境優雅的重啟基於Nginx、Tornado的Web服務進程
阿新 • • 發佈:2018-09-03
進程關閉 nod add ocs unix 內部 start logfile stop
Nginx是一個高效的Web服務器及代理服務器,Tornado是一個基於epoll的異步Web開發框架,通常使用Nginx做為Web服務器時,都會以FastCGI模式,而我們從開發、調試、運維的角度考慮,使用了反向代理的模式,同時Nginx可以做一些特殊業務和負載均衡的處理。
其實反向代理模式很簡單,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 .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中):
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 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()
|
生產環境優雅的重啟基於Nginx、Tornado的Web服務進程