19.熔断器使用(4):通用降级方法的编写姿势

很多时候我们一个service有很多响应类型,当请求超时或者失败的时候熔断器会调用降级服务,并返回值,但是我们熔断器一个service只定义了一次,所以具体应该返回哪个类型的response我们不知道,所以可以使用下面的通用方法来解决这个问题

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: 5000,
    }
    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}
}




原文地址:https://www.cnblogs.com/hualou/p/12133565.html