30.普通API集成到go-micro体系中(2):代码注册与反注册

首先理一下思路,使用代码去注册其他api到go-micro体系中,我们就需要在代码中模拟出这样的json数据,并发送给我们的micro Registry服务

{
    "jsonrpc": "2.0",
    "method": "Registry.Deregister",
    "params": [{
        "name": "api.jtthink.com.test",
        "version": "1.0",
        "endpoints": [],
        "nodes": [{
            "address": "192.168.29.1",
            "id": "userservice-uuid",
            "port": 8088
        }]
    }],
    "id": 1
}

首先我们构造结构体,构建一个这样的结构体,然后把需要的数据填充进去序列化成json发送给micro Registry就完成了我们的需求

package sidecar

type JSONRequest struct {
    Jsonrpc string
    Method  string
    Params  []*Service
    Id      int
}

func NewJSONRequest(service *Service, endpoint string) *JSONRequest {
    return &JSONRequest{Jsonrpc: "2.0", Method: endpoint, Params: []*Service{service}, Id: 1}
}

把之前的json拆成小的结构体再填充数据整合

type Service struct {
   Name  string
   Nodes []*ServiceNode
}
{
        "name": "api.jtthink.com.test",
        "version": "1.0", //在上面的结构体中version和endpints我们暂时不传
        "endpoints": [],
        "nodes": [{
            "address": "192.168.29.1",
            "id": "userservice-uuid",
            "port": 8088
        }
}
type ServiceNode struct {
   Id      string //服务ID,不能重复
   Port    int
   Address string
}
{
            "address": "192.168.29.1",
            "id": "userservice-uuid",
            "port": 8088
        }

实现注册与反注册的函数

package sidecar

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

type Service struct {
    Name  string
    Nodes []*ServiceNode
}
type ServiceNode struct {
    Id      string //服务ID,不能重复
    Port    int
    Address string
}

func NewService(name string) *Service {
    return &Service{Name: name, Nodes: make([]*ServiceNode, 0)}
}
func NewServiceNode(id string, port int, address string) *ServiceNode {
    return &ServiceNode{Id: id, Port: port, Address: address}
}
func (this *Service) AddNode(id string, port int, address string) {
    this.Nodes = append(this.Nodes, NewServiceNode(id, port, address))
}

var RegistryURI = "http://localhost:8000"

func requestRegistry(jsonrequest *JSONRequest) error { //关键代码。用来请求注册器
    b, err := json.Marshal(jsonrequest)
    if err != nil {
        log.Fatal(err)
        return err
    }
    rsp, err := http.Post(RegistryURI, "application/json", bytes.NewReader(b))//发送Post请求到Registry的地址带上我们的json数据,就可以成功注册啦
    if err != nil {
        return err
    }
    defer rsp.Body.Close()
    res, err := ioutil.ReadAll(rsp.Body)
    if err != nil {
        return err
    }
    fmt.Println(string(res)) //打印出结果
    return nil
}

func UnRegService(service *Service) error  {
    return requestRegistry(NewJSONRequest(service,"Registry.Deregister")) //反注册只需要改一下endpoint为Registry.Deregister就可以了
}
func RegService(service *Service) error {
    return requestRegistry(NewJSONRequest(service,"Registry.Register"))
}

启用三方api并注册到我们的go-micro体系中

package main

import (
    "context"
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
    "log"
    "micro/sidecar"
    "net/http"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    ginRouter := gin.Default()
    v1 := ginRouter.Group("/v1")
    {
        v1.Handle("POST", "/test", func(context *gin.Context) {
            context.JSON(200, gin.H{
                "data": "test",
            })
        })
    }
    server := &http.Server{
        Addr:    ":8088",
        Handler: ginRouter,
    }
    service := sidecar.NewService("api.jtthink.com.test")
    service.AddNode("test-"+uuid.New().String(), 8088, "localhost:8088")
    handler := make(chan error)
    go func() {
        handler <- server.ListenAndServe()
    }()
    go (func() {
        server.ListenAndServe()
    })()
    go func() {
        notify := make(chan os.Signal)
        signal.Notify(notify, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
        handler <- fmt.Errorf("%s", <-notify)
    }()
    //注册服务
    go func() {
        err := sidecar.RegService(service)
        if err != nil {
            handler <- err
        }
    }()
    getHandler := <-handler //阻塞一旦有错误发生,err写入信道,解除阻塞,执行反注册服务
    fmt.Println(getHandler.Error())
    //反注册服务
    err := sidecar.UnRegService(service)
    if err != nil {
        log.Fatal(err)
    }
    err = server.Shutdown(context.Background())
    if err != nil {
        log.Fatal(err)
    }

}

调用第三方服务

package main

import (
    "context"
    "fmt"
    "github.com/micro/go-micro/client"
    "github.com/micro/go-micro/client/selector"
    "github.com/micro/go-micro/registry"
    "github.com/micro/go-micro/registry/etcd"
    myhttp "github.com/micro/go-plugins/client/http"
    "log"
)

func main() {
    etcdReg := etcd.NewRegistry(registry.Addrs("106.12.72.181:23791"))

    mySelector := selector.NewSelector(
        selector.Registry(etcdReg),
        selector.SetStrategy(selector.RoundRobin),
    )
    getClient := myhttp.NewClient(client.Selector(mySelector), client.ContentType("application/json"))

    //1创建request
    req := getClient.NewRequest("api.jtthink.com.test", "/v1/test", map[string]string{}) //这里的request
    //2创建response
    var rsp map[string]interface{} //var rsp map[string]string这里这么写也可以,因为我们的返回值是{"data":"test"},所以都对的上
    err := getClient.Call(context.Background(), req, &rsp) //将返回值映射到map中
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(rsp)
}

调用结果





posted @ 2020-01-03 20:50  离地最远的星  阅读(457)  评论(0编辑  收藏  举报