Go-Micro微服务框架速学

1,引入外部框架gin生成web API

go版本为1.14

go-micro升级到1.14之后的一些变动和安装方式,确保你开启了go module模式

先装
 go get github.com/micro/go-micro

然后装plugins
go get github.com/micro/go-plugins

1,如果出现

 请参考 这个帖子: https://github.com/golang/go/issues/34394

解决方法:在go.mod里加入
replace github.com/gogo/protobuf v0.0.0-20190410021324-65acae22fc9 => github.com/gogo/protobuf v0.0.0-20190723190241-65acae22fc9d
然后再执行安装:go get github.com/micro/go-plugins

2,如果出现 

则可以这样:

首先安装 (注意后面的@master)
 go get github.com/lucas-clemente/quic-go@master

 然后在go.mod里面找到 版本号  譬如是 
   github.com/lucas-clemente/quic-go v0.7.1-0.20191025234737-672328ca3059

然后 在go.mod里加入
replace github.com/lucas-clemente/quic-go => github.com/lucas-clemente/quic-go v0.7.1-0.20191025234737-672328ca3059

此时可以再次执行go get github.com/micro/go-micro (注意不要加-u)

有可能你会发现  go-plugins 木有consul相关内容;

那就只能这样了: go get github.com/micro/go-plugins@master

Github地址: https://github.com/micro/go-micro

本课程一律使用go module的方式 安装

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/micro/go-micro/web"
)

func main(){

    ginRouter:=gin.Default()
    ginRouter.Handle("GET","/user", func(context *gin.Context) {
         context.String(200,"user api")
    })
    ginRouter.Handle("GET","/news", func(context *gin.Context) {
        context.String(200,"news api")
    })
    server:=web.NewService(
        web.Address(":8001"),
        web.Handler(ginRouter),
        )

    server.Run()

}

2,服务注册:快速把服务注册到etcd中

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/micro/go-micro/registry"
    "github.com/micro/go-micro/registry/etcd"
    "github.com/micro/go-micro/web"
)

func main(){
     etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))

    ginRouter:=gin.Default()
    ginRouter.Handle("GET","/user", func(context *gin.Context) {
         context.String(200,"user api")
    })
    ginRouter.Handle("GET","/news", func(context *gin.Context) {
        context.String(200,"news api")
    })
    server:=web.NewService(
        web.Name("api.jtthink.com.prodservice"),
        web.Address(":8001"),
        web.Handler(ginRouter),
        web.Registry(etcdReg),
        )

    server.Run()

}

web.bat

set MICRO_REGISTRY=etcd
set MICRO_REGISTRY_ADDRESS=localhost:2379
set MICRO_API_NAMESPACE=api.jtthink.com
micro web

3,模拟运行API(主站API、商品API) 服务注册 服务发现

服务注册

首选编写服务端  服务注册到go-micro中

package ProdService

import "strconv"

type ProdModel struct {
    ProdID int
    ProdName string
}

func NewProd(id int,pname string ) *ProdModel  {
    return &ProdModel{ProdName:pname,ProdID:id}
}
func NewProdList(n int) []*ProdModel {
    ret:=make([]*ProdModel,0)
    for i:=0;i<n;i++{
        ret=append(ret,NewProd(100+i,"prodname"+strconv.Itoa(100+i)))
    }
    return ret
}
D:gocode1.14.3gocodego-microProdServiceProdModels.go
package main

import (
	"github.com/gin-gonic/gin"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/registry/etcd"
	"github.com/micro/go-micro/web"
	"gomicro.jtthink.com/ProdService"
)

func main(){
	 etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))

	ginRouter:=gin.Default()
	v1Group:=ginRouter.Group("/v1")
	{
		v1Group.Handle("GET","/prods", func(context *gin.Context) {
			context.JSON(200,ProdService.NewProdList(5))
		})
	}
	server:=web.NewService(
		web.Name("prodservice"),
		web.Address(":8001"),
		web.Handler(ginRouter),
		web.Registry(etcdReg),
		)

	server.Run()

}

 go run ./prod_main.go

 服务发现

获取consul服务列表、selector随机选择

                           

 test.go

package main

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

func main()  {
    etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))
    getService,err:=etcdReg.GetService("prodservice")
    if err!=nil{
        log.Fatal(err)
    }
    next:=selector.Random(getService)
    node,err:=next()
    if err!=nil{
        log.Fatal(err)
    }
    fmt.Println(node.Id,node.Address,node.Metadata)


}
D:gocode1.14.3gocodego-micro>go run test.go
6925a735-58c3-4148-92fa-d560d80d3bb7 192.168.1.101:8001 map[]

4,使用内置命令参数启动,注册多个服务

Go-micro 内置了 一些参数,可以在启动时 指定,这样就不用写死了

譬如地址: 我们可以 这样运行 go run prod_main.go --server_address :8001 别忘了,加上 server.Init()

server:=web.NewService(
		web.Name("prodservice"),
		//web.Address(":8001"),
		web.Handler(ginRouter),
		web.Registry(etcdReg),
		)

	server.Init()
	server.Run()

  

开启多个服务,用轮训方式获取服务

服务端:

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/micro/go-micro/registry"
    "github.com/micro/go-micro/registry/etcd"
    "github.com/micro/go-micro/web"
    "gomicro.jtthink.com/ProdService"
)

func main(){
     etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))

    ginRouter:=gin.Default()
    v1Group:=ginRouter.Group("/v1")
    {
        v1Group.Handle("GET","/prods", func(context *gin.Context) {
            context.JSON(200,ProdService.NewProdList(5))
        })
    }
    server:=web.NewService(
        web.Name("prodservice"),
        //web.Address(":8001"),
        web.Handler(ginRouter),
        web.Registry(etcdReg),
        )

    server.Init()
    server.Run()

}

启动服务 并注册服务

go run prod_main.go --server_address :8001

go run prod_main.go --server_address :8002

go run prod_main.go --server_address :8003

客户端:

用轮训方式调用服务

package main

import (
    "fmt"
    "github.com/micro/go-micro/client/selector"
    "github.com/micro/go-micro/registry"
    "github.com/micro/go-micro/registry/etcd"
    "log"
    "time"
)

func main()  {
    //etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))
    //getService,err:=etcdReg.GetService("prodservice")
    //if err!=nil{
    //    log.Fatal(err)
    //}
    //next:=selector.Random(getService)
    //node,err:=next()
    //if err!=nil{
    //    log.Fatal(err)
    //}
    //fmt.Println(node.Id,node.Address,node.Metadata)

    for {
        etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))
        getService,err:=etcdReg.GetService("prodservice")
        if err!=nil{
            log.Fatal(err)
        }
        next:=selector.RoundRobin(getService)
        node,err:=next()
        if err!=nil{
            log.Fatal(err)
        }
        fmt.Println( node.Address)
        time.Sleep(time.Second*1)
    }
}
D:gocode1.14.3gocodego-micro>go run  test.go
192.168.1.101:8002
192.168.1.101:8001
192.168.1.101:8003
192.168.1.101:8002
192.168.1.101:8001
192.168.1.101:8003

启动web管理界面:

web.bat

set MICRO_REGISTRY=etcd
set MICRO_REGISTRY_ADDRESS=localhost:2379
set MICRO_API_NAMESPACE=prodservice
micro web

5,服务调用:基本方式调用 Api(http api)

package main

import (
    "fmt"
    "github.com/micro/go-micro/v2/client/selector"
    "github.com/micro/go-micro/v2/registry/etcd"
    "github.com/micro/go-micro/v2/registry"
    "io/ioutil"
    "log"
    "net/http"
)

func callAPI(addr string,path string,method string) (string,error)  {
    req,_:=http.NewRequest(method,"http://"+addr+path,nil)
    client:=http.DefaultClient
    res,err:=client.Do(req)
    if err!=nil{
        return "",err
    }
    defer res.Body.Close()
    buf,_:= ioutil.ReadAll(res.Body)
    return string(buf),nil
}
func main()  {
    etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))
    getService,err:=etcdReg.GetService("prodservice")
    if err!=nil{
        log.Fatal(err)
    }
    next:=selector.Random(getService)
    node,err:=next()
    if err!=nil{
        log.Fatal(err)
    }
    fmt.Println(node.Id,node.Address,node.Metadata)

    callRes,err:=callAPI(node.Address,"/v1/prods","GET")
    if err!=nil{
        log.Fatal(err)
    }
    fmt.Println(callRes)

    //for {
    //    etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379"))
    //    getService,err:=etcdReg.GetService("prodservice")
    //    if err!=nil{
    //        log.Fatal(err)
    //    }
    //    next:=selector.RoundRobin(getService)
    //    node,err:=next()
    //    if err!=nil{
    //        log.Fatal(err)
    //    }
    //    fmt.Println( node.Address)
    //    time.Sleep(time.Second*1)
    //}
}

返回结果:

D:gocode1.14.3gocodego-micro>go run  test.go
0b93cd42-ba4d-4dcc-afee-73eb00e87547 192.168.1.101:8002 map[]
[{"ProdID":100,"ProdName":"prodname100"},{"ProdID":101,"ProdName":"prodname101"},{"ProdID":102,"ProdName":"prodname102"},
{"ProdID":103,"ProdName":"prodna me103"},{"ProdID":104,"ProdName":"prodname104"}]

 服务调用_ 使用插件、调用http api的正规姿势(初步)

 使用插件

https://github.com/micro/go-plugins

这里面包含了很多go-micro可选插件。譬如服务注册中心要选择etcd、eureka等,就需要使用到插件(当然,手工玩耍也行)

安装go get github.com/micro/go-plugins
这个不多说了

http 包

对应的http调用包: import myhttp "github.com/micro/go-plugins/client/http " 此包除了有 http client基本功能,还支持Selector参数,

自动选取服务,并支持json、protobuf等数据格式

 

原文地址:https://www.cnblogs.com/sunlong88/p/12952907.html