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 main
import (
"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, // 超时时间 100ms
MaxConcurrentRequests: 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.Person
ctx, 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)
}
}