從nginx熱更新聊一聊Golang中的伺服器熱更新(上)
靜態語言在伺服器編程時都會遇到這樣的問題:如何保證已有的連接服務不中斷同時又升級版本?
最近花了點時間看了下nginx熱更新代碼流程,想了下結合之前的經驗一併總結下熱更新
1. 熱更新是什麼?
簡單翻譯成人類可讀的實例是如下這個樣子:
舉個例子,你現在在坐卡車,卡車開到了150KM/H
然後,有個輪胎,爆了
然後,司機說,你就直接換吧,我不停車。你小心點換嗯。就這個意思
2.網關中的熱更新
服務程序熱更新
這個問題在層7網關中尤其嚴重,網關中承載著大量的請求,包括HTTP/HTTPS短連接
、HTTP/HTTPS長連接
、甚至是websocket
這種超長連接(websocket通常連接時間會很長,十幾分鐘到幾天不等)。這樣的話我們勢必不能講服務程序停止再啟動的冷更新
,服務進程熱更新
是非常有必要的。
網關作為一個基礎組件,需要保證高可用,是很難將其先停下來再更新的;
有人說可以使用負載均衡將需要更新的組件先隔離,再停機更新,但是如果是一個很小的集群沒有負載均衡呢,又或者這樣手動一台一台升級也著實麻煩,部分情況下就算隔離了也不過是不會有新的連接過來,舊的連接/請求依舊需要處理完成,否則就會造成部分服務不可用。
不過實際上線上操作是集群隔離加熱更新一起操作
3.nginx熱更新(Upgrading Executable on the Fly)
nginx [engine x]
是Igor Sysoev
編寫的一個HTTP和反向代理伺服器
,另外它也可以作為郵件代理伺服器。 它已經在眾多流量很大的俄羅斯網站上使用了很長時間,這些網站包括Yandex
、Mail.Ru
、VKontakte
,以及Rambler
。據Netcraft
統計,在2012年8月份,世界上最繁忙的網站中有11.48%
使用Nginx
作為其伺服器或者代理伺服器。
NginX採用
Master/Worker
的多進程模型,Master
進程負責整個NginX
進程的管理。Nginx
的模塊化
、熱更新
、Http處理流程
、日誌
等機制都非常經典。這裡將會簡要介紹一下熱更新的機制
3.1 nginx熱升級流程
步驟1、升級nginx二進位文件
,需要先將新的nginx可執行文件
替換原有舊的nginx文件
,然後給nginx master進程
發送USR2信號
,告知其開始升級可執行文件;nginx master進程
會將老的pid
文件增加.oldbin後綴
,然後拉起新的master
和worker進程
,並寫入新的master進程的pid
。
UID PID PPID C STIME TTY TIME CMD
root 4584 1 0 Oct17 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 12936 4584 0 Oct26 ? 00:03:24 nginx: worker process
root 12937 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 12938 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 23692 4584 0 21:28 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 23693 23692 3 21:28 ? 00:00:00 nginx: worker process
root 23694 23692 3 21:28 ? 00:00:00 nginx: worker process
root 23695 23692 3 21:28 ? 00:00:00 nginx: worker process
步驟2、在此之後,所有工作進程(包括舊進程和新進程)
將會繼續接受請求。這時候,需要發送WINCH
信號給nginx master進程
,master進程
將會向worker進程
發送消息,告知其需要進行graceful shutdown
,worker進程
會在連接處理完之後進行退出。
UID PID PPID C STIME TTY TIME CMD
root 4584 1 0 Oct17 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 12936 4584 0 Oct26 ? 00:03:24 nginx: worker process
root 12937 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 12938 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 23692 4584 0 21:28 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
#若舊的worker進程還需要處理連接,則worker進程不會立即退出,需要待消息處理完後再退出
步驟3、經過一段時間之後,將會只會有新的worker進程處理新的連接。
注意,
舊master進程
並不會關閉它的listen socket
;因為如果出問題後,需要回滾,master進程需要法重新啟動它的worker進程。
步驟4、如果升級成功,則可以向舊master進程
發送QUIT信號,停止老的master進程
;如果新的master進程
(意外)退出,那麼舊master進程
將會去掉自己的pid文件的.oldbin後綴。
3.2 nginx熱更新相關信號
master進程相關信號
USR2 升級可執行文件
WINCH 優雅停止worker進程
QUIT 優雅停止master進程
worker進程相關信號
TERM, INT 快速退出進程
QUIT 優雅停止進程