zoukankan      html  css  js  c++  java
  • 根据服务名调用地址优雅调用服务

    package util
    
    import (
        "context"
        "go.etcd.io/etcd/clientv3"
        "io/ioutil"
        "net/http"
        "regexp"
        "time"
    )
    
    type Client struct {
        client   *clientv3.Client
        Services []*ServiceInfo
    }
    
    type ServiceInfo struct {
        ServiceID   string
        ServiceName string
        ServiceAddr string
    }
    
    func NewClient() *Client {
        config := clientv3.Config{
            Endpoints:   []string{"106.12.72.181:23791", "106.12.72.181:23792"},
            DialTimeout: 10 * time.Second,
        }
        client, _ := clientv3.New(config)
        return &Client{client: client}
    }
    
    func (this *Client) LoadService() error {
        kv := clientv3.NewKV(this.client)
        res, err := kv.Get(context.TODO(), "/services", clientv3.WithPrefix())
        if err != nil {
            return err
        }
        for _, item := range res.Kvs {
            this.parseService(item.Key, item.Value)
        }
        return nil
    }
    func (this *Client) parseService(key []byte, value []byte) {
        reg := regexp.MustCompile("/services/(\w+)/(\w+)")
        if reg.Match(key) {
            idandname := reg.FindSubmatch(key)
            sid := idandname[1]
            sname := idandname[2]
            this.Services = append(this.Services, &ServiceInfo{ServiceID: string(sid),
                ServiceName: string(sname), ServiceAddr: string(value)})
        }
    }
    
    //定义一个高阶函数返回处理具体url的函数
    func (this *Client) GetService(sname string, method string, encodeFunc EncodeRequestFunc) Endpoint {
        for _, service := range this.Services {
            if service.ServiceName == sname {
                return func(ctx context.Context, requestParam interface{}) (responseResult interface{}, err error) {
                    httpClient := &http.Client{}
                    httpRequest, err := http.NewRequest(method, "http://"+service.ServiceAddr, nil)
                    if err != nil {
                        return nil, err
                    }
                    err = encodeFunc(ctx, httpRequest, requestParam) //这一步是关键,将httpRequest的url修改了
                    if err != nil {
                        return nil, err
                    }
                    res, err := httpClient.Do(httpRequest)
                    defer res.Body.Close()
                    body, err := ioutil.ReadAll(res.Body)
                    if err != nil {
                        return err, nil
                    }
                    return string(body), nil
                }
            }
        }
        return func(ctx context.Context, requestParam interface{}) (responseResult interface{}, err error) {
            return nil, err
        }
    }
    

    各个url处理的函数类型申明

    package util
    
    import (
        "context"
        "net/http"
    )
    //request是调用参数,response是返回结果
    type Endpoint func(ctx context.Context,requestParam interface{})(responseResult interface{},err error)
    
    //决定请求path以及参数
    type EncodeRequestFunc func(context.Context,*http.Request,interface{}) error
    

    各个url处理的函数类型实现

    package serivces
    
    import (
        "context"
        "net/http"
        "strconv"
    )
    
    func ProdEncodeFunc(ctx context.Context,httpRequest *http.Request, requestParams interface{}) error {
        prodr:=requestParams.(ProdRequest)
        httpRequest.URL.Path+="/product/"+strconv.Itoa(prodr.ProdId)
        return nil
    }

    怎么调用这些函数

    package main
    
    import (
        "context"
        "fmt"
        "goetcd/services"
        "goetcd/util"
        "log"
    )
    
    
    
    func main()  {
        client:=util.NewClient()
        err:=client.LoadService()
        if err!=nil{
            log.Fatal(err)
        }
        endpoint:=client.GetService("productservice","GET", serivces.ProdEncodeFunc)
        res,err:= endpoint(context.Background(),serivces.ProdRequest{ProdId:106})
        if err!=nil{
            log.Fatal(err)
        }
        fmt.Println(res)
    }




  • 相关阅读:
    软件測试系列之软件測试过程模型(四)
    实例具体解释Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)
    Hadoop-2.2.0中文文档—— MapReduce 下一代
    const vs readonly
    oracle-asm
    Javascript 笔记与总结(2-15)结构、样式、行为分离
    [Swift]LeetCode455. 分发饼干 | Assign Cookies
    [Swift]LeetCode453. 最小移动次数使数组元素相等 | Minimum Moves to Equal Array Elements
    [Swift]LeetCode448. 找到所有数组中消失的数字 | Find All Numbers Disappeared in an Array
    [Swift]LeetCode443. 压缩字符串 | String Compression
  • 原文地址:https://www.cnblogs.com/hualou/p/12071079.html
Copyright © 2011-2022 走看看