17.熔斷器使用(3):初步整合hystrix到go-micro中


使用go-micro的裝飾器整合熔斷器

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 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) //調用rpc api接口
    }, func(e error) error { //降級函數
        defaultProds(rsp)
        return nil
    })
}

func NewProdsWrapper(c client.Client) client.Client {
    return &ProdsWrapper{c}
}

調用中間件

package main

import (
    "context"
    "fmt"
    "github.com/micro/go-micro"
    "github.com/micro/go-micro/client"
    "github.com/micro/go-micro/registry"
    "github.com/micro/go-micro/web"
    "github.com/micro/go-plugins/registry/consul"
    "go-micro/Services"
    "go-micro/Weblib"
    "go-micro/Wrappers"
)

type logWrapper struct {
    client.Client
}

func (this *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
    fmt.Println("調用接口") //這樣每一次調用調用接口時都會
    return this.Client.Call(ctx, req, rsp)
}
func NewLogWrapper(c client.Client) client.Client {
    return &logWrapper{c}
}
func main() {
    consulReg := consul.NewRegistry( //新建一個consul注冊的地址,也就是我們consul服務啟動的機器ip+端口
        registry.Addrs("localhost:8500"),
    )
    //下面兩局代碼是注冊rpcserver調用客戶端
    myService := micro.NewService(
        micro.Name("prodservice.client"),
        micro.WrapClient(NewLogWrapper),            //在注冊時只需要傳入方法名即可,底層會自動給這個方法傳入client
        micro.WrapClient(Wrappers.NewProdsWrapper), //在注冊時只需要傳入方法名即可,底層會自動給這個方法傳入client
    )
    prodService := Services.NewProdService("prodservice", myService.Client()) //生成的這個客戶端綁定consul中存儲的prodservice服務,只要調用了prodservice接口就會調用我們上面注冊的中間件



    //其實下面這段代碼的作用就是啟動webserver的同事的時候把服務注冊進去
    httpserver := web.NewService( //go-micro很靈性的實現了注冊和反注冊,我們啟動后直接ctrl+c退出這個server,它會自動幫我們實現反注冊
        web.Name("httpprodservice"),                   //注冊進consul服務中的service名字
        web.Address(":8001"),                          //注冊進consul服務中的端口,也是這里我們gin的server地址
        web.Handler(Weblib.NewGinRouter(prodService)), //web.Handler()返回一個Option,我們直接把ginRouter穿進去,就可以和gin完美的結合
        web.Registry(consulReg),                       //注冊到哪個服務器上的consul中
    )
    httpserver.Init() //加了這句就可以使用命令行的形式去設置我們一些啟動的配置
    httpserver.Run()
}





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM