Gong服務實現平滑重啟分析

2021-10-03 07:00:17 字數 3823 閱讀 2833

平滑重啟是指能讓我們的程式在重啟的過程不中斷服務,新老程序無縫銜接,實現零停機時間(zero-downtime)部署;

目前實現平滑重啟的主要策略有兩種:

方案一:我們的服務如果是多機器部署,可以通過閘道器程式,將即將重啟服務的機器從閘道器下線,重啟完成後再重新上線,該方案適合多機器部署的企業級應用;

方案二:讓我們的程式實現自啟動,重啟子程序來實現平滑重啟,核心策略是通過拷貝檔案描述符實現子程序和父程序切換,適合單機器部署應用;

實現原理介紹

http 連線介紹:

我們知道,http 服務也是基於 tcp 連線,我們通過 golang http 包原始碼也能看到底層是通過監聽 tcp 連線實現的;

func (srv *server) listenandserve() error 

addr := srv.addr

if addr == ""

ln, err := net.listen("tcp",addr)

if err !=nil

return srv.serve(tcpkeepalivelistener)

}

復用 socket:

當程式開啟 tcp 連線監聽時會建立乙個 socket 並返回乙個檔案描述符 handler 給我們的程式; 

通過拷貝檔案描述符檔案可以使 socket 不關閉繼續使用原有的埠,自然 http 連線也不會斷開,啟動乙個相同的程序也不會出現埠被占用的問題;

通過如下**進行測試:

}該程式啟動後,等待 5s 會自動 fork 子程序,通過 ps 命令檢視如圖可以看到有兩個程序同時共存:

然後我們可以通過瀏覽器訪問 可以看到會隨機顯示主程序或子程序的輸出;

寫乙個測試**進行迴圈請求:

能看到返回的資料也是有些是主程序有些是子程序。

切換過程:

在開啟新的程序和老程序退出的瞬間,會有乙個短暫的瞬間是同時有兩個程序使用同乙個檔案描述符,此時這種狀態,通過http請求訪問,會隨機請求到新程序或老程序上,這樣也沒有問題,因為請求不是在新程序上就是在老程序上;當老程序結束後請求就會全部到新程序上進行處理,通過這種方式即可實現平滑重啟;

綜上,我們可以將核心的實現總結如下:

1.監聽退出訊號;

2.監聽到訊號後 fork 子程序,使用相同的命令啟動程式,將檔案描述符傳遞給子程序;

3.子程序啟動後,父程序停止服務並處理正在執行的任務(或超時)退出;

4.此時只有乙個新的程序在執行,實現平滑重啟。

乙個完整的 demo **,通過傳送 usr1 訊號,程式會自動建立子程序並關閉主程序,實現平滑重啟:

}使用 apache 的 ab 壓測工具進行驗證一下,執行 ab -c 50 -t 20 持續 50 的併發 20s,在壓測的期間向程式執行的pid傳送 usr1 訊號,可以看到壓測結果,沒有失敗的請求,由此可知,該方案實現平滑重啟是木有問題的。

最後給大家安利乙個 web 開發框架,該框架已經將平滑重啟進行的封裝,開箱即用,快速構建乙個帶平滑重啟的 web 服務。

框架原始碼:

文件:

nginx 平滑重啟的實現方法

一 背景 在伺服器開發過程中,難免需要重啟服務載入新的 或配置,如果能夠保證server重啟的過程中服務不間斷,那重啟對於業務的影響可以降為0。最近調研了一下nginx平滑重啟,覺得很有意思,記錄下來供有興趣的同學查閱。二 重啟流程 三 nginx實現 為了驗證nginx平滑重啟,筆者首先嘗試ngi...

surging EFCore 服務實現入門

本篇文章基於上篇基礎上進行的,請先了解此篇 surging centos7 docker rancher2.0 菜鳥部署執行筆記 開發環境 visual studio 2017 15.5 資料庫 sql server 2012 執行環境 虛擬機器centos 7 docker rancher 2.0...

平台日誌服務實現思路

每個業務系統都需記錄操作日誌的共性,現狀是每個業務系統都需要記錄在自己的資料庫中 如叢林系統操作日誌 會存在重複建設問題。有些系統還沒有操作日誌,如專題 廣告 配置系統等。部分的業務系統操作記錄資料量不算太大,但是記錄是很有必要的,可以排查問題等。不排除以後會快速增長,如果還記錄在自己業務系統的資料...