前言:看源碼遇到了一個(gè)監(jiān)督樹(shù)的概念,好好探索一番
什么是監(jiān)督樹(shù)
我覺(jué)得監(jiān)控樹(shù)就是一種以樹(shù)的形式管理多個(gè)進(jìn)程/線程/協(xié)程(后面統(tǒng)一說(shuō)進(jìn)程)的程序設(shè)計(jì)模型。這一種模型基于 worker 和 supervisor 的思想。
- worker 就是用于工作的進(jìn)程。
- supervisor 就是用于監(jiān)控 worker 的進(jìn)程。supervisor 在某一個(gè) worker 出問(wèn)題的時(shí)候可以重新啟動(dòng) worker。
典型的 Supervision Tree 如下圖所示(圖片來(lái)自這里):

方框代表著 supervisor
圓框代表著 worker
1 表示 one_for_one
a 表示 one_for_all
one_for_one vs one_for_all
前者表示 worker failed 的時(shí)候,它的 supervisor 只重啟這一個(gè) worker。適用于在同一層的 worker 互不依賴的情況。
后者表示 worker failed 的時(shí)候,它的 supervisor 重啟這一層的所有 worker。適用于同一層的 worker 互相依賴的情況。
在 Go 中如何應(yīng)用
Supervision Tree 本是 Erlang 中的一個(gè)重要概念,但是有大佬把他移植到了 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 會(huì)嘗試重啟 s2 s3 一定次數(shù)。