<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
專案開發過程中,隨著需求的迭代,程式碼的釋出會頻繁進行,在釋出過程中,如何讓程式做到優雅的退出?
為什麼需要優雅的退出?
如下我們以 http 服務,gRPC 服務,單獨的 woker 協程為例子,一步步說明平滑關閉的寫法。
為了解決退出可能出現的潛在問題,平滑關閉一般做如下一些事情
原來的寫法
// startHttpServer start http server func startHttpServer() { mux := http.NewServeMux() // mux.Handle("/metrics", promhttp.Handler()) if err := http.ListenAndServe(":1608", mux); err != nil { log.Fatal("startHttpServer ListenAndServe error: " + err.Error()) } }
帶平滑關閉的寫法
// startHttpServer start http server func startHttpServer() { mux := http.NewServeMux() // mux.Handle("/metrics", promhttp.Handler()) srv := &http.Server{ Addr: ":1608", Handler: mux, } // 註冊平滑關閉,退出時會呼叫 srv.Shutdown(ctx) quit.GetQuitEvent().RegisterQuitCloser(srv) if err := srv.ListenAndServe(); err != nil { log.Fatal("startHttpServer ListenAndServe error: " + err.Error()) } }
把平滑關閉註冊到http.Server的關閉函數中
// startHttpServer start http server func startHttpServer() { mux := http.NewServeMux() // mux.Handle("/metrics", promhttp.Handler()) srv := &http.Server{ Addr: ":1608", Handler: mux, } // 把平滑退出註冊到http.Server中 srv.RegisterOnShutdown(quit.GetQuitEvent().GracefulStop) if err := srv.ListenAndServe(); err != nil { log.Fatal("startHttpServer ListenAndServe error: " + err.Error()) } }
原來的寫法
// startGrpcServer start grpc server func startGrpcServer() { listen, err := net.Listen("tcp", "0.0.0.0:9999") if err != nil { log.Fatalf("Failed to listen: %v", err) return } grpcServer := grpc.NewServer() // helloBoot.GrpcRegister(grpcServer) go grpcServer.Serve(listen) defer grpcServer.GracefulStop() // ... }
帶平滑關閉的寫法
// startGrpcServer start grpc server func startGrpcServer() { listen, err := net.Listen("tcp", "0.0.0.0:9999") if err != nil { log.Fatalf("Failed to listen: %v", err) return } grpcServer := grpc.NewServer() // helloBoot.GrpcRegister(grpcServer) go grpcServer.Serve(listen) // 把 grpc 的GracefulStop註冊到退出事件中 quit.GetQuitEvent().RegisterStopFunc(grpcServer.GracefulStop) quit.WaitSignal() }
單獨的協程啟停,可以通過計數的方式註冊到退出事件處理器中。
1.啟動協程 增加計數
quit.GetQuitEvent().AddGoroutine()
2.停止協程 減計數
quit.GetQuitEvent().DoneGoroutine()
3.常駐後臺執行的協程退出的條件改成退出事件是否結束的條件
!quit.GetQuitEvent().HasFired()
4.常駐後臺執行的協程若通過 select 處理 chan,同時增加退出事件的chan
case <-quit.GetQuitEvent().Done()
// myWorker my worker type myWorker struct { } // RunWorkerWithChan run Goroutine worker func (m *myWorker) RunWorkerWithChan() { // 啟動一個Goroutine時,增加Goroutine數 quit.GetQuitEvent().AddGoroutine() defer func() { // 一個Goroutine退出時,減少Goroutine數 quit.GetQuitEvent().DoneGoroutine() }() // 退出時,此次退出 for !quit.GetQuitEvent().HasFired() { select { // 退出時,收到退出訊號 case <-quit.GetQuitEvent().Done(): break //case msg := <- m.YouChan: // handle msg } } } // RunWorker run Goroutine worker func (m *myWorker) RunWorker() { // 啟動一個Goroutine時,增加Goroutine數 quit.GetQuitEvent().AddGoroutine() defer func() { // 一個Goroutine退出時,減少Goroutine數 quit.GetQuitEvent().DoneGoroutine() }() // 退出時,此次退出 for !quit.GetQuitEvent().HasFired() { // ... } }
實現 io.Closer 介面的結構體,增加到退出事件處理器中
// startMyService start my service func startMyService() { srv := NewMyService() // 註冊平滑關閉,退出時會呼叫 srv.Close() quit.GetQuitEvent().RegisterCloser(srv) srv.Run() } // myService my service type myService struct { isStop bool } // NewMyService new func NewMyService() *myService { return &myService{} } // Close my service func (m *myService) Close() error { m.isStop = true return nil } // Run my service func (m *myService) Run() { for !m.isStop { // .... } }
退出訊號處理由某一框架接管,尋找框架如何註冊退出函數,優秀的框架一般都會實現安全實現退出的機制。
如下將退出事件註冊到某一框架的平滑關閉函數中
func startMyServer() { // ... // xxx框架退出函數註冊退出事件 xxx.RegisterQuitter(func() { quit.GetQuitEvent().GracefulStop() }) }
以上就是Golang實現程式優雅退出的方法詳解的詳細內容,更多關於Golang程式退出的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45