• 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等数据格式

     

  • 相关阅读:
    RHEL5.8使用yum安装xclock
    Linux下磁盘分区、挂载、卸载操作记录
    CentOS6.5磁盘分区和挂载操作记录
    CentOS环境下下调整home和根分区大小
    PowerDesigner连接Oracle数据库(32位)反向生成物理数据模型
    Create-React-App脚手架使用方法
    react 简书开发笔记
    本地连接服务器的mongodb
    使用mongoose连接mongodb(转载文章)
    将koa+vue部署到服务器
  • 原文地址:https://www.cnblogs.com/sunlong88/p/12952907.html
Copyright © 2020-2023  润新知