前言:看源碼遇到了一個監督樹的概念,好好探索一番
什么是監督樹
我覺得監控樹就是一種以樹的形式管理多個進程/線程/協程(后面統一說進程)的程序設計模型。這一種模型基于 worker 和 supervisor 的思想。
- worker 就是用于工作的進程。
- supervisor 就是用于監控 worker 的進程。supervisor 在某一個 worker 出問題的時候可以重新啟動 worker。
典型的 Supervision Tree 如下圖所示(圖片來自這里):
方框代表著 supervisor
圓框代表著 worker
1 表示 one_for_one
a 表示 one_for_all
one_for_one vs one_for_all
前者表示 worker failed 的時候,它的 supervisor 只重啟這一個 worker。適用于在同一層的 worker 互不依賴的情況。
后者表示 worker failed 的時候,它的 supervisor 重啟這一層的所有 worker。適用于同一層的 worker 互相依賴的情況。
在 Go 中如何應用
Supervision Tree 本是 Erlang 中的一個重要概念,但是有大佬把他移植到了 Go 上:https://github.com/thejerf/suture。
從 https://pkg.go.dev/github.com/thejerf/suture/v4 這上面可以看到具體怎么使用。
具體用法
package main
import (
"context"
"errors"
"fmt"
"github.com/thejerf/suture/v4"
"time"
)
type SimpleServer struct {
Name string
Time time.Duration
}
func (s *SimpleServer) Serve(ctx context.Context) error {
for {
fmt.Println(s.Name)
time.Sleep(s.Time)
}
}
type ReturnErrorServer struct {
}
func (s *ReturnErrorServer) Serve(ctx context.Context) error {
return errors.New("some stupid error")
}
type PanicServer struct {
}
func (s *PanicServer) Serve(ctx context.Context) error {
panic("panic")
return nil
}
func main() {
ctx := context.TODO()
r := suture.New("root", suture.Spec{})
s1 := &SimpleServer{"s1", time.Second}
s2 := &ReturnErrorServer{}
s3 := &PanicServer{}
r.Add(s1)
r.Add(s2)
r.Add(s3)
_ = r.Serve(ctx)
}
可以看到不斷輸出 s1,supervsior 會嘗試重啟 s2 s3 一定次數。