1. 程式人生 > >生產環境優雅的重啟基於Nginx、Tornado的Web服務進程

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

進程關閉 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服務進程