hystrix是一个容错库,旨在隔离指向远程系统,服务和第三方库的请求,杜绝级联故障,并在复杂的分布式系统中实现弹性,毕竟在分布式系统中,故障是不可避免的。
关闭:服务正常,并维护一个失败率统计,当失败率达到阀值时,转到开启状态开启:服务异常,调用 fallback 函数,一段时间之后,进入半开启状态半开启:尝试恢复服务,失败率高于阀值,进入开启状态,低于阀值,进入关闭状态
文档:https://godoc.org/github.com/afex/hystrix-go/hystrix
Variables
var (// 超时,单位毫秒DefaultTimeout = 1000//可以同时运行相同类型的命令的数量,最大并发数DefaultMaxConcurrent = 10//请求阈值 熔断器是否打开首先要满足这个条件;//这里的设置表示至少有20个请求才进行ErrorPercentThreshold错误百分比计算DefaultVolumeThreshold = 20//熔断器开启后,过多久进行恢复测试。单位毫秒DefaultSleepWindow = 5000//错误率DefaultErrorPercentThreshold = 50// DefaultLogger is the default logger that will be used in the Hystrix package. By default prints nothing.DefaultLogger = NoopLogger{})
func Do(name string, run runFunc, fallback fallbackFunc) error
- 以同步的方式运行函数,直到函数成功或返回一个错误,这个错误是runFunc与fallbackFunc的合并错误
type CommandConfig
CommandConfig用于在运行时调优电路设置type CommandConfig struct {Timeout int `json:"timeout"`MaxConcurrentRequests int `json:"max_concurrent_requests"`RequestVolumeThreshold int `json:"request_volume_threshold"`SleepWindow int `json:"sleep_window"`ErrorPercentThreshold int `json:"error_percent_threshold"`}
grpc熔断
package mainimport ("context""fmt""github.com/afex/hystrix-go/hystrix""google.golang.org/grpc"pb "study/grpc/protobuf/person""time""errors")const (address = "localhost:8080"defaultId = 1)func main() {// 熔断器hystrix.ConfigureCommand("myservice", // 熔断器名字,可以用服务名称命名,一个名字对应一个熔断器,对应一份熔断策略hystrix.CommandConfig{Timeout: 2000, // 超时时间 100msMaxConcurrentRequests: 2, // 最大并发数,超过并发返回错误RequestVolumeThreshold: 4, // 请求数量的阀值,用这些数量的请求来计算阀值ErrorPercentThreshold: 25, // 错误率阀值,达到阀值,启动熔断,25%SleepWindow: 5000, // 熔断尝试恢复时间,1000ms},)conn, err := grpc.Dial(address, grpc.WithInsecure())if err != nil{return}defer conn.Close()for {var res *pb.Personctx, cancel := context.WithTimeout(context.Background(), time.Second*2)defer cancel()client :=pb.NewPersonserverClient(conn)err = hystrix.Do("myservice", func() error {res,err = client.GetPerson(ctx,&pb.PersonFilter{Id:1})return err}, func(e error) error {// 失败处理逻辑,访问其他资源失败时,或者处于熔断开启状态时,会调用这段逻辑// 可以简单构造一个response返回,也可以有一定的策略,比如访问备份资源// 也可以直接返回 err,这样不用和远端失败的资源通信,防止雪崩// 这里因为我们的场景太简单,所以我们可以在本地在作一个加法就可以了return errors.New("失败处理......")})if err != nil{fmt.Println(err)time.Sleep(2*time.Second)continue}fmt.Printf("%+v",res)fmt.Println()time.Sleep(1*time.Second)}}

