這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
文章來源:http://gf.johng.cn/625833
基本介紹
平滑重啟(熱重啟)是指Web Server在重啟的時候不會中斷已有請求的執行。該特性在不同的項目版本發布的時候特別有用,例如,當需要先後發布兩個版本:A、B,那麼在A執行的過程當中,我們可以將B的程式直接發布覆蓋A的程式,並使用平滑重啟特性無縫地將請求過渡到新版本的服務中。
需要注意的是,該特性僅限於*nix
系統(Linux/Unix/FreeBSD等等),在Windows下僅支援完整重啟功能(請求無法平滑過渡)。
管理功能
gf架構支援非常方便的Web管理功能,也就是說我們可以通過Web頁面/介面直接進行Web Server的重啟/關閉等管理操作。同時,gf架構也支援通過命令列終端指令(僅限*nix
系統)的形式進行Web Server的重啟/關閉等管理操作。
Web管理
我們先來看一下Web Server中涉及到管理操作方法有哪些:
func (s *Server) Reload() errorfunc (s *Server) Restart() errorfunc (s *Server) Shutdown() errorfunc (s *Server) EnableAdmin(pattern ...string)
其中,Reload
用於平滑重啟,Restart
用於完整重啟,Shutdown
用於關閉Web Server。我們可以隨時在註冊的服務處理介面中調用這3個方法來實現Web Server的管理操作。
此外,gf架構提供了一個簡便的管理方法EnableAdmin
,用於將管理頁面註冊到指定的路由規則上,預設地址是/debug/admin
。
樣本1:基本使用
package mainimport ( "time" "gitee.com/johng/gf/g" "gitee.com/johng/gf/g/os/gproc" "gitee.com/johng/gf/g/net/ghttp")func main() { s := g.Server() s.BindHandler("/", func(r *ghttp.Request){ r.Response.Writeln("哈嘍!") }) s.BindHandler("/pid", func(r *ghttp.Request){ r.Response.Writeln(gproc.Pid()) }) s.BindHandler("/sleep", func(r *ghttp.Request){ r.Response.Writeln(gproc.Pid()) time.Sleep(10*time.Second) r.Response.Writeln(gproc.Pid()) }) s.EnableAdmin() s.SetPort(8199) s.Run()}
我們通過以下幾個步驟來測試平滑重啟:
- 訪問 http://127.0.0.1:8199/pid 查看當前進程的pid
- 訪問 http://127.0.0.1:8199/sleep ,這個頁面將會執行10秒,用於測試重啟時該頁面請求執行是否會斷掉
- 訪問 http://127.0.0.1:8199/debug/admin ,這是
s.EnableAdmin
後預設註冊的一個Web Server管理頁面
隨後我們點擊reload
管理連結,Web Server將會立即平滑重啟
同時在終端也會輸出以下資訊:
2018-05-18 11:02:04.812 11511: http server started listening on [:8199]2018-05-18 11:02:09.172 11511: server reloading2018-05-18 11:02:09.176 16358: http server reloaded listening on [:8199]
- 我們可以發現在整個操作中,
sleep
頁面的執行並沒有被中斷,繼續等待幾秒,當sleep
執行完成後,頁面輸出內容為:
- 可以發現,
sleep
頁面輸出的進程pid和之前的不一樣了,代表請求的執行被新的進程平滑接管,舊的服務進程也隨之銷毀;
樣本2:HTTPS支援
package mainimport ( "gitee.com/johng/gf/g" "gitee.com/johng/gf/g/net/ghttp")func main() { s := g.Server() s.BindHandler("/", func(r *ghttp.Request){ r.Response.Writeln("哈羅!") }) s.EnableHTTPS("/home/john/temp/server.crt", "/home/john/temp/server.key") s.EnableAdmin() s.SetPort(8200) s.Run()}
gf架構的平滑重啟特性對於HTTPS的支援也是相當友好和簡便,操作步驟如下:
- 訪問 https://127.0.0.1:8200/debug/admin/reload 平滑重啟HTTPS服務;
- 訪問 https://127.0.0.1:8200/debug/admin/shutdown 平滑關閉Web Server服務;
在命令列終端可以看到以下輸出資訊:
2018-05-18 11:13:05.554 17278: https server started listening on [:8200]2018-05-18 11:13:21.270 17278: server reloading2018-05-18 11:13:21.278 17319: https server reloaded listening on [:8200]2018-05-18 11:13:34.895 17319: server shutting down2018-05-18 11:13:34.895 17269: all servers shutdown
樣本3:多服務及多連接埠
gf架構的平滑重啟特性相當強大及穩定,不僅僅支援單一服務單一連接埠監聽管理,同時也支援多服務多連接埠等複雜情境的監聽管理。
package mainimport ( "gitee.com/johng/gf/g")func main() { s1 := g.Server("s1") s1.EnableAdmin() s1.SetPort(8100, 8200) s1.Start() s2 := g.Server("s2") s2.EnableAdmin() s2.SetPort(8300, 8400) s2.Start() g.Wait()}
以上樣本示範的是兩個Web Server s1
及s2
,分別監聽8100
,8200
及8300
,8400
。我們隨後訪問 http://127.0.0.1:8100/debug/admin/reload 平滑重啟服務,然後再通過 http://127.0.0.1:8100/debug/admin/shutdown 平滑關閉服務,最終在終端列印出的資訊如下:
2018-05-18 11:26:54.729 18111: http server started listening on [:8400]2018-05-18 11:26:54.729 18111: http server started listening on [:8100]2018-05-18 11:26:54.729 18111: http server started listening on [:8300]2018-05-18 11:26:54.729 18111: http server started listening on [:8200]2018-05-18 11:27:08.203 18111: server reloading2018-05-18 11:27:08.207 18124: http server reloaded listening on [:8300]2018-05-18 11:27:08.207 18124: http server reloaded listening on [:8400]2018-05-18 11:27:08.207 18124: http server reloaded listening on [:8200]2018-05-18 11:27:08.207 18124: http server reloaded listening on [:8100]2018-05-18 11:27:19.379 18124: server shutting down2018-05-18 11:27:19.380 18102: all servers shutdown
命令列管理
gf架構除了提供Web方式的管理能力以外,也支援命令列方式來進行管理,由於命令列採用了訊號量進行管理,因此僅支援*nix
系統。
主進程與子進程
gf架構的平滑重啟特性是依靠多進程管理及處理序間通訊來實現的,因此Web Server程式執行後將會存在兩個進程,並且有主/子進程之分。假如我們的Web Server程式名稱叫做demo
,執行運行之後,我們通過ps
命令查看進程情況:
$ ps aux | grep demojohn 19557 0.1 0.1 282408 10676 ? Sl 11:53 0:00 /tmp/demojohn 19566 0.0 0.1 356140 10688 ? Sl 11:53 0:00 /tmp/demo --gproc-child
其中,命令列帶有--gproc-child
參數標識的是子進程,是Web Server真實提供服務的進程;另外一個是主進程,用於對子進程進行狀態監控和行為管理。任何時刻,系統中只會存在一個程式的主進程,以及一個對應的子進程,不會存在多個主進程或者子進程的情況。
平滑重啟
使用SIGUSR1
訊號量實現,使用方式:kill -SIGUSR1 主進程ID
完整重啟
使用SIGUSR2
訊號量實現,使用方式:kill -SIGUSR2 主進程ID
關閉服務
使用SIGINT/SIGQUIT/SIGKILL/SIGHUP/SIGTERM
其中任一一個訊號量來實現,使用方式:kill -SIGTERM 主進程ID
其他管理方式
由於gf架構的Web Server採用了單例設計,因此任何地方都可以通過g.Server(名稱)
或者ghttp.GetServer(名稱)
來獲得對應Web Server的單例對象,隨後通過Reload
、Restart
和Shutdown
方法可以實現對該Web Server的管理。