首先理一下思路,使用代码去注册其他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)
}
调用结果