监督树(Supervision Tree)在 Go 中的应用

前言:看源码遇到了一个监督树的概念,好好探索一番

什么是监督树

我觉得监控树就是一种以树的形式管理多个进程/线程/协程(后面统一说进程)的程序设计模型。这一种模型基于 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 一定次数。

参考

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容