hystrix是一个容错库,旨在隔离指向远程系统,服务和第三方库的请求,杜绝级联故障,并在复杂的分布式系统中实现弹性,毕竟在分布式系统中,故障是不可避免的。

  • 关闭:服务正常,并维护一个失败率统计,当失败率达到阀值时,转到开启状态
  • 开启:服务异常,调用 fallback 函数,一段时间之后,进入半开启状态
  • 半开启:尝试恢复服务,失败率高于阀值,进入开启状态,低于阀值,进入关闭状态

文档:https://godoc.org/github.com/afex/hystrix-go/hystrix

Variables

  1. var (
  2. // 超时,单位毫秒
  3. DefaultTimeout = 1000
  4. //可以同时运行相同类型的命令的数量,最大并发数
  5. DefaultMaxConcurrent = 10
  6. //请求阈值 熔断器是否打开首先要满足这个条件;
  7. //这里的设置表示至少有20个请求才进行ErrorPercentThreshold错误百分比计算
  8. DefaultVolumeThreshold = 20
  9. //熔断器开启后,过多久进行恢复测试。单位毫秒
  10. DefaultSleepWindow = 5000
  11. //错误率
  12. DefaultErrorPercentThreshold = 50
  13. // DefaultLogger is the default logger that will be used in the Hystrix package. By default prints nothing.
  14. DefaultLogger = NoopLogger{}
  15. )

func Do(name string, run runFunc, fallback fallbackFunc) error

  • 以同步的方式运行函数,直到函数成功或返回一个错误,这个错误是runFunc与fallbackFunc的合并错误

    type CommandConfig

    CommandConfig用于在运行时调优电路设置
    1. type CommandConfig struct {
    2. Timeout int `json:"timeout"`
    3. MaxConcurrentRequests int `json:"max_concurrent_requests"`
    4. RequestVolumeThreshold int `json:"request_volume_threshold"`
    5. SleepWindow int `json:"sleep_window"`
    6. ErrorPercentThreshold int `json:"error_percent_threshold"`
    7. }

grpc熔断

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/afex/hystrix-go/hystrix"
  6. "google.golang.org/grpc"
  7. pb "study/grpc/protobuf/person"
  8. "time"
  9. "errors"
  10. )
  11. const (
  12. address = "localhost:8080"
  13. defaultId = 1
  14. )
  15. func main() {
  16. // 熔断器
  17. hystrix.ConfigureCommand(
  18. "myservice", // 熔断器名字,可以用服务名称命名,一个名字对应一个熔断器,对应一份熔断策略
  19. hystrix.CommandConfig{
  20. Timeout: 2000, // 超时时间 100ms
  21. MaxConcurrentRequests: 2, // 最大并发数,超过并发返回错误
  22. RequestVolumeThreshold: 4, // 请求数量的阀值,用这些数量的请求来计算阀值
  23. ErrorPercentThreshold: 25, // 错误率阀值,达到阀值,启动熔断,25%
  24. SleepWindow: 5000, // 熔断尝试恢复时间,1000ms
  25. },
  26. )
  27. conn, err := grpc.Dial(address, grpc.WithInsecure())
  28. if err != nil{
  29. return
  30. }
  31. defer conn.Close()
  32. for {
  33. var res *pb.Person
  34. ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
  35. defer cancel()
  36. client :=pb.NewPersonserverClient(conn)
  37. err = hystrix.Do("myservice", func() error {
  38. res,err = client.GetPerson(ctx,&pb.PersonFilter{Id:1})
  39. return err
  40. }, func(e error) error {
  41. // 失败处理逻辑,访问其他资源失败时,或者处于熔断开启状态时,会调用这段逻辑
  42. // 可以简单构造一个response返回,也可以有一定的策略,比如访问备份资源
  43. // 也可以直接返回 err,这样不用和远端失败的资源通信,防止雪崩
  44. // 这里因为我们的场景太简单,所以我们可以在本地在作一个加法就可以了
  45. return errors.New("失败处理......")
  46. })
  47. if err != nil{
  48. fmt.Println(err)
  49. time.Sleep(2*time.Second)
  50. continue
  51. }
  52. fmt.Printf("%+v",res)
  53. fmt.Println()
  54. time.Sleep(1*time.Second)
  55. }
  56. }

image.png