如果熔断器只设置timeout参数,那么只是解决了报错后服务怎么处理的问题,但是每次请求都会两秒,但是如果请求的服务一直很慢,那么每次至少要等待timeout的时间才会调用降级方法返回结果,这是相当慢的,所以我们可以设置其他参数,让熔断器在服务请求超时或失败一定次数后,以后接受到请求直接走降级方法,这样就提高了响应的速度
代码如下
package Wrappers
import (
"context"
"github.com/afex/hystrix-go/hystrix"
"github.com/micro/go-micro/client"
"go-micro/Services"
"strconv"
)
type ProdsWrapper struct { //官方提供的例子,创建自己的struct,嵌套go-micro的client
client.Client
}
//通用降级方法
func defaultData(rsp interface{}) { //通过定义这个方法使得我们熔断器降级调用后自动判断类型并返回正确的类型
switch t := rsp.(type) {
case *Services.ProdListResponse:
defaultProds(rsp)
case *Services.ProdDetailResponse:
t.Data = newProd(10, "优衣库")
}
}
//商品列表降级方法
func defaultProds(rsp interface{}) { //将rsp中传入响应值,这里响应值是我们proto定义好的返回值
models := make([]*Services.ProdModel, 0)
var i int32
for i = 0; i < 5; i++ {
models = append(models, newProd(20+i, "prodname"+strconv.Itoa(20+int(i))))
}
result := rsp.(*Services.ProdListResponse) //类型断言为我们定义好的返回值
result.Data = models
}
func newProd(i int32, s string) *Services.ProdModel {
return &Services.ProdModel{ProdID: i, ProdName: s}
}
//重写Call方法
func (this *ProdsWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
cmdName := req.Service() + "." + req.Endpoint() //req.Service()是服务名.Endpoint是方法,这里是ProdService.GetProdsList,这个名字并不会对结果有影响,只是这里规范定义而已,其实定义hello world也可以运行
/*
service ProdService{
rpc GetProdsList (ProdsRequest) returns (ProdListResponse);
}
*/
configA := hystrix.CommandConfig{
Timeout: 2000,
RequestVolumeThreshold: 2, //并发数,同时处理的请求
ErrorPercentThreshold: 20, //当请求达到20个开始熔断判断
SleepWindow: 5000, //熔断器打开之后,过5秒再次开始判断这个方法是否ok
}
hystrix.ConfigureCommand(cmdName, configA)
return hystrix.Do(cmdName, func() error {
return this.Client.Call(ctx, req, rsp) //
}, func(e error) error {
defaultData(rsp) //通用降级方法调用
return nil
})
}
func NewProdsWrapper(c client.Client) client.Client {
return &ProdsWrapper{c}
}