在Uber FX中,實作後台程序正常關閉的正確方法是什麼?這是許多人在使用Uber FX時經常遇到的問題。作為一個強大的後台任務處理框架,Uber FX提供了一種簡單而有效的方法來管理和處理後台任務。 php小編子墨將在本文中為您介紹如何正確關閉後台進程,確保程式的穩定性和正常運作。
假設我的 Uber FX 應用程式中有一個服務,它應該執行一些後台活動,例如輪詢外部 API。 我可以透過觸發 goroutine 來運行後台任務,但是停止它們的正確方法是什麼?
作為一種可能的實現,讓我們考慮以下範例:
package main import ( "context" "log" "sync" "time" "go.uber.org/fx" ) type AwesomeService struct { // context to use for background processes bg context.Context // to trigger background processes stopping cancel context.CancelFunc // to wait for background processes to gracefully finish wg *sync.WaitGroup } func New(lc fx.Lifecycle) *AwesomeService { bg, cancel := context.WithCancel(context.Background()) service := &AwesomeService{ bg: bg, cancel: cancel, wg: new(sync.WaitGroup), } lc.Append(fx.Hook{ OnStart: service.start, OnStop: service.stop, }) return service } func (s *AwesomeService) start(_ context.Context) error { s.runBackgroundProcess() log.Println("Start done") return nil } func (s *AwesomeService) stop(_ context.Context) error { s.cancel() s.wg.Wait() log.Println("Stop done") return nil } // runBackgroundProcess does some work till context is done. func (s *AwesomeService) runBackgroundProcess() { s.wg.Add(1) go func() { defer s.wg.Done() for { select { case <-s.bg.Done(): return case <-time.After(1 * time.Second): log.Println("Working...") } } }() } func main() { fx.New( fx.Provide(New), fx.Invoke(func(*AwesomeService) {}), ).Run() }
一些注意事項:
fx.Lifecycle
掛鉤連接到應用程式生命週期。 OnStart
/OnStop
方法中的上下文,因為它們是不同的上下文並且對應於啟動/停止活動,而不是應用生命週期上下文。 疑慮與問題:
在我看來,使用上下文就很好,但是您也可以透過通道向您想要的任何 Go 例程傳達關閉訊號。請參閱下面的範例程式碼。
是的,您還應該等待等待群組計數返回零,然後再完全關閉應用程式。所以你首先要關閉通道,然後在等待群組上等待。
package main import ( "context" "log" "sync" "time" "go.uber.org/fx" ) type AwesomeService struct { // channel to shutdown background processes shutdown chan struct{} // to wait for background processes to gracefully finish wg *sync.WaitGroup } func New(lc fx.Lifecycle) *AwesomeService { service := &AwesomeService{ shutdown: make(chan struct{}), wg: new(sync.WaitGroup), } lc.Append(fx.Hook{ OnStart: service.start, OnStop: service.stop, }) return service } func (s *AwesomeService) start(_ context.Context) error { s.runBackgroundProcess() log.Println("Start done") return nil } func (s *AwesomeService) stop(_ context.Context) error { close(s.shutdown) s.wg.Wait() log.Println("Stop done") return nil } // runBackgroundProcess does some work till context is done. func (s *AwesomeService) runBackgroundProcess() { s.wg.Add(1) go func() { defer s.wg.Done() for { select { case <-s.shutdown: return case <-time.After(1 * time.Second): log.Println("Working...") } } }() } func main() { fx.New( fx.Provide(New), fx.Invoke(func(*AwesomeService) {}), ).Run() }
以上是在 Uber FX 中實現後台進程正常關閉的正確方法是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!