Go-Micro 环境搭建

269 阅读3分钟

安装

go-micro

官方Github

go-micro的repo其实有些混乱,以及除了go-micro之外,还有一个micro的repo,两者之间的关系我暂时还没搞懂(似乎micro可安装后对go-micro进行查看)

安装go-micro的v3版本

go get -u github.com/asim/go-micro/v3

如果出问题记得设置

go env -w GO111MODULE=on

go-micro plugins

go-micro在v1和v2采用go-plugins的一个单独repo Github,但在v3的时候又重新回到了go-micro/plugins下面Github

v3

go get -u github.com/asim/go-micro/plugins/registry/consul/v3

安装 Protobuf 相关工具

接下来,安装基于 Protobuf 格式服务声明文件自动生成微服务原型代码所需要的一些工具。

安装 protoc-gen-micro

首先是 protoc-gen-micro,该工具适用于在 Micro 框架中基于 Protobuf 文件生成服务代码,在项目根目录下运行如下 go get 命令安装:

go get github.com/micro/micro/v3/cmd/protoc-gen-micro@master
​
// 到 protoc-gen-micro 根目录下安装,bin 文件会到 $GoPath:\bin\
go install .// 把 $GoPath:\bin\ 添加到系统环境变量的 Path

安装protobuf

protobuf介绍自行搜索,类似json但占用更小的空间 在官方Github里的release下载最新的包,选择对应的os,比如我下载的是protoc-3.14.0-win64.zip(不懂为什么一群人教程下32位)

放到想要的安装目录下,D:\repository\protoc-22.0-rc-3-win64\bin,把bin目录加入环境变量

命令行

>protoc --version
libprotoc 22.0-rc3

安装protoc-gen-go

protobuf默认是不支持go的编译的,因此需要安装protoc-gen-go来支持编译为go文件

go get google.golang.org/protobuf/cmd/protoc-gen-go@v1.28// 到 protoc-gen-go 根目录下安装,bin 文件会到 $GoPath:\bin\
go install .

consul

这里下了一个docker镜像包,因为本身也准备用docker,安装在电脑上似乎没那么必要

docker pull consul
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul agent -server -bootstrap-expect=1 -ui -bind=0.0.0.0 -client=0.0.0.0

浏览器localhost:8500,可以看到当前已注册的服务

测试服务

至此,我们已经做好了所有外围的准备工作,接下来,可以正式通过 Go Micro 框架编写第一个微服务接口了。

服务接口声明

在项目的根目录下新建一个 proto 子目录,然后在 proto 目录下创建一个 Protobuf 格式的服务接口声明文件 greeter.proto

syntax = "proto3";
​
package proto;
option go_package = "/proto";
​
service Greeter {
  rpc Hello(Request) returns (Response) {}
}
​
message Request {
  string name = 1;
}
​
message Response {
  string greeting = 1;
}

如上述代码所示,我们定义了一个名为 Greeter 的服务

通过服务声明生成原型代码

接下来,我们就可以借助前面安装的 protoc 工具通过服务声明文件生成相应的服务原型代码(在项目根目录下运行):

protoc --micro_out=. --go_out=. proto/greeter.proto

HelloWorld微服务

这里我们创建一个service和一个client,模拟最简单的微服务的交互场景(代码改编于go-micro/example/service)

目录结构

文件夹go-micro-test

│  client.gogo.mod
│  go.sum
│  greeter.go
│
└─proto
        greeter.pb.go
        greeter.pb.micro.go
        greeter.proto

定义proto

如果采用GoLand开发的话推荐安装插件Protocol Buffer Editor,网上看到推荐Protobuf Support已经被deprecated了

greeter.proto
syntax = "proto3";
​
package proto;
option go_package = "/proto";
​
service Greeter {
  rpc Hello(Request) returns (Response) {}
}
​
message Request {
  string name = 1;
}
​
message Response {
  string greeting = 1;
}

这里定义了一个叫做Greeter的调用方法(client对service的rpc),其中Request就是请求的数据内容,Response就是service返回的内容 package是生成的文件的包名,go_package是总的包路径

生成对应go文件:

protoc --micro_out=. --go_out=. proto/greeter.proto

获得greeter.pb.gogreeter.pb.micro.go

编写service

这里叫做greeter.go

package main
​
import (
    "context"
    "github.com/asim/go-micro/plugins/registry/consul/v3"
    "github.com/asim/go-micro/v3"
    "github.com/asim/go-micro/v3/registry"
    proto "go-micro-test/proto"
    "log"
)
​
type Greeter struct{}
​
func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error {
    rsp.Greeting = "Hello " + req.Name
    return nil
}
​
func main() {
    consulReg := consul.NewRegistry(registry.Addrs(":8500"))
​
    service := micro.NewService(
        micro.Name("greeter"),
        micro.Registry(consulReg),
    )
​
    service.Init()
​
    proto.RegisterGreeterHandler(service.Server(), new(Greeter))
​
    if err := service.Run(); err != nil {
        log.Fatal(err)
    }
}

这里Greeter和它的方法Hello是用来实现我们在proto中定义的调用

编写client

文件client.go

package main
​
import (
    "context"
    "fmt"
    "github.com/asim/go-micro/plugins/registry/consul/v3"
    "github.com/asim/go-micro/v3"
    "github.com/asim/go-micro/v3/registry"
    proto "go-micro-test/proto"
)
​
func main() {
    consulReg := consul.NewRegistry(registry.Addrs(":8500"))
​
    service := micro.NewService(
        micro.Name("greeter.client"),
        micro.Registry(consulReg),
    )
​
    service.Init()
​
    greeter := proto.NewGreeterService("greeter", service.Client())
​
    rsp, err := greeter.Hello(context.TODO(), &proto.Request{Name: "World"})
    if err != nil {
        fmt.Println(err)
        return
    }
​
    fmt.Println(rsp.Greeting)
}

运行

首先启动ervice

go run greeter.go

其次启动client

go run client.go

如无意外可以看到client这边显示Hello World