摘要:上篇大致提到的的熱更新,本篇將詳細論述。軟件的熱更新就是指在保持系統正常運行的情況下對系統進行更新升級。同樣地,熱更新也可以采取類似的處理。注包方式的熱更新本文暫不討論。
上篇大致提到的Golang的熱更新,本篇將詳細論述。
1、什么是熱更新網絡上有這么一個例子來形容熱更新,我覺得很形象很貼切:
一架行駛在高速上的大卡車,行駛過程中突然遭遇爆胎,熱更新則是要求在不停車的情況下將車胎修補好,且補胎過程中卡車需要保持正常行駛。
軟件的熱更新就是指在保持系統正常運行的情況下對系統進行更新升級。常見的情況有:系統服務升級、修復現有邏輯、服務配置更新等。
2、熱更新原理先來看下Nginx熱更新是如何做的?
Nginx支持運行中接收信號,方便開發者控制進程。
1)首先備份原有的Nginx二進制文件,并用新編譯好的Nginx二進制文件替換舊的
2)然后向master進程發送USR2信號。此時Nginx進程會啟動一個新版本Nginx,該新版本Nginx進程會發起一個新的master進程與work進程。即此時會有兩個Nginx實例在運行,一起處理新來的請求。
3)再向原master進程發送WINCH信號,它會逐漸關閉相關work進程,此時原master進程仍保持監聽新請求但不會發送至其下work進程,而是交給新的work進程
4)最后等到所有原work進程全部關閉,向原master進程發送QUIT信號,終止原master進程,至此,完成Nginx熱升級。
注:在*nix系統中,信號(Signal)是一種進程間通信機制,它給應用程序提供一種異步的軟件中斷,使應用程序有機會接受其他程序或終端發送的命令(即信號)。
同樣地,Golang熱更新也可以采取類似的處理。如上篇所述,都是利用用戶自定義信號USR2。
注:Plugin包方式的Golang熱更新本文暫不討論。
3、熱更新實現Golang熱更新可以細分為服務熱『更新』(即熱升級,類比Nginx的restart命令)與配置文件熱更新(類比Nginx的reload命令)。接下來從實現細節處依次討論。
3.1 服務熱更新大致流程如下:
1)Golang服務進程運行時監聽USR2信號
2)進程收到USR2信號后,fork子進程(啟動新版本服務),并將當前socket句柄等進程環境交給它
3)新進程開始監聽socket請求
4)等待舊服務連接停止
主要代碼示例如下:
監聽USR2信號
func (a *app) signalHandler(wg *sync.WaitGroup) { ch := make(chan os.Signal, 10) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR2) for { sig := <-ch switch sig { case syscall.SIGINT, syscall.SIGTERM: // 確保接收到INT/TERM信號時可以觸發Golang標準的進程終止行為 signal.Stop(ch) a.term(wg) return case syscall.SIGUSR2: err := a.preStartProcess() if err != nil { a.errors <- err } // 發起新進程 if _, err := a.net.StartProcess(); err != nil { a.errors <- err } } } }
復制當前進程socket連接,發起新進程
execSpec := &syscall.ProcAttr{ Env: os.Environ(), Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, } fork, err := syscall.ForkExec(os.Args[0], os.Args, execSpec) ...
詳細源碼可見:https://scalingo.com/articles...
以上僅為代碼示例,目前已經成熟的開源實現主要有:endless和facebook的grace,原理基本類似,fork一個子進程,子進程監聽原有父進程socket端口,父進程優雅退出。
在實際的生產環境中推薦使用以上開源庫,關于熱更新開源庫的使用非常方便,下面是facebook的grace庫的例子:
引入github.com/facebookgo/grace/gracehttp包
func main() { app := gin.New()// 項目中時候的是gin框架 router.Route(app) var server *http.Server server = &http.Server{ Addr: ":8080", Handler: app, } gracehttp.Serve(server) }
利用go build命令編譯,生成服務的可執行文件。
然后再用shell封裝一下服務命令,生成restat.sh命令文件
#!/bin/sh ps aux | grep wingo count=`ps -ef | grep "wingo" | grep -v "grep" | wc -l` echo "" if [ 0 == $count ]; then echo "Wingo starting..." sudo ./wingo & echo "Wingo started" else echo "Wingo Restarting..." sudo kill -USR2 $(ps -ef | grep "wingo" | grep -v grep | awk "{print $2}") echo "Wingo Restarted" fi sleep 1 ps aux | grep wingo
注:其中wingo為服務的二進制名稱。
于是,便可通過執行./restart.sh命令,達到對服務的熱升級目的。
3.2 配置文件熱更新配置文件熱更新是指在不停止服務的情況下,重新加載服務所有配置文件。
與3.1服務熱升級原理一樣,利用用戶自定義信號:USR1,即可實現服務的配置文件熱更新。
1)服務監聽USR1信號
2)服務接收到USR1信號后,停止接受新的連接,等待當前連接停止,重新載入配置文件,重啟服務器,從而實現相對平滑的不停服的更改。
主要代碼實現:
// LoadAllConf 調用加載配置文件函數 // load為具體加載配置文件方法 func LoadAllConf(load func(bool)) { load(true) listenSIGUSR1(load) } // listenSIGUSR1 監聽SIGUSR1信號 func listenSIGUSR1(f func(bool)) { s := make(chan os.Signal, 1) signal.Notify(s, syscall.SIGUSR1) go func() { for { <-s f(false) log.Println("Reloaded") } }() }
詳細源碼可見:https://www.openmymind.net/Go...
利用go build命令編譯,生成服務的可執行文件。
然后再用shell封裝一下配置重載命令,生成reload.sh命令文件
#!/bin/sh ps aux | grep wingo echo "" echo "Wingo Reloading..." sudo kill -USR1 $(ps -ef | grep "wingo" | grep -v grep | awk "{print $2}") echo "Wingo Reloaded" echo "" sleep 1 ps aux | grep wingo
于是,便可通過執行./reload.sh命令,達到對服務的配置文件熱升級目的。
4、總結本文主要描述了Golang服務熱升級與配置文件熱更新原理與主要代碼實現,本質上也不是什么新內容,如果之前讀過《Unix環境高級編程》,就會覺得很親切。底層原理基本上是利用了信號這個軟件中斷機制,在運行中改變常駐進程的行為。
Referenceshttps://scalingo.com/articles...
http://kuangchanglang.com/gol...
https://blog.csdn.net/black_O...
https://www.openmymind.net/Go...
https://blog.csdn.net/qq_1543...
https://wrfly.kfd.me/posts/%E...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29722.html
摘要:但是,隨著微服務架構的興起以及容器時代的到來,這種情況又再次加劇。最重要的是,在微服務與容器領域有很好的基礎,后期系統可完美實現微服務化與容器化。 1、Why Not PHP 使用PHP構建的WEB程序,隨著業務發展到一定體量之后,都不得不面臨以下一些問題: 業務功能不斷擴張,如何避免某單一業務功能故障影響整體,維持系統健壯性 業務邏輯復雜度不斷上升,如何解耦與模塊化,降低系統復雜性...
摘要:的本質是團隊博客,關注互聯網創業技術,每周推薦篇優質文章。堅持爭取做到每周更新,與讀者一起進步。第十一期第十期第九期第八期第七期第六期第五期第四期第三期切換至,第二期發布。創刊,用發布了第一次。 Tuniu Weekly Inspired By 《灣區日報》 我們團隊也想基于這種模式,讓大家感受到技術的人文。 《Tuniu Weekly》就這樣產生了。 《Tuniu Weekly》...
摘要:目的為了減少重復和新項目的配置麻煩等問題,就是為了騙星星如現有的生成工具雖然好用,但是不太喜歡樣式和代碼結構。有些本地,測試,線上的配置需要頻繁改動的需要。 目的 為了減少重復 CURD 和新項目的配置麻煩等問題,(就是為了騙星星:LaravelPlus )如: 現有的 infyomlabs/laravel-generator CODE 生成工具雖然好用,但是不太喜歡樣式和代碼結構。...
摘要:作者介紹劉春輝,洪超,一業務場景是東南亞和臺灣地區領先的電子商務平臺,覆蓋新加坡馬來西亞菲律賓印度尼西亞泰國越南和臺灣等七個市場。母公司為首家在紐約證券交易所上市的東南亞互聯網企業。 作者介紹劉春輝,Shopee DBA洪超,Shopee DBA 一、業務場景 Shopee(https://shopee.com/)是東南亞和臺灣地區領先的電子商務平臺,覆蓋新加坡、馬來西亞、菲律賓、印...
閱讀 4549·2021-09-10 11:22
閱讀 530·2019-08-30 11:17
閱讀 2564·2019-08-30 11:03
閱讀 430·2019-08-29 11:18
閱讀 3455·2019-08-28 17:59
閱讀 3218·2019-08-26 13:40
閱讀 3157·2019-08-26 10:29
閱讀 1136·2019-08-26 10:14