本文主要将如何快速启动 M3O 微服务
快速上手
依赖 Protobuf
代码生成依赖 Protobuf , 安装示例:
1 go get github.com/micro/protoc-gen-micro/v2
Discovery
推荐使用 etcd 作为注册中心。
etcd
单机部署参考 Dockerfile, 安装示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 FROM k8s.gcr.io/debian-base:v1.0.0 ADD etcd /usr/local /bin/ ADD etcdctl /usr/local /bin/ RUN mkdir -p /var/etcd/ RUN mkdir -p /var/lib/etcd/ RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf EXPOSE 2379 2380 CMD ["/usr/local/bin/etcd" ]
使用当前目录作为上下文的构建命令:
安装 go-micro Go Micro是用于基于Go的开发的框架。
服务中导入 go-micro 示例:
1 import "github.com/micro/go-micro/v2"
建议开启 go mod,并通过 go mod 启用改功能。
1 2 3 4 5 6 export GO111MODULE=ongo mod init go get ./...
编写服务 按照惯例,使用 go-micro 编写一个 helloworld服务,以下是具体步骤。
服务原型
生成原型
编写服务
运行服务
定义客户端
运行客户端
以下操作均在 greeter 目录下进行。
服务原型 创建 proto 目录
编辑 proto/greeter.proto 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 syntax = "proto3"; service Greeter { rpc Hello(HelloRequest) returns (HelloResponse) {} } message HelloRequest { string name = 1; } message HelloResponse { string greeting = 2; }
查看下 greeter 目录,可以看到 proto 目录中只有 greeter.proto 文件。
1 2 3 4 5 greeter ├── go.mod ├── go.sum └── proto └── greeter.proto
生成原型 在定义好原型后我们得使用 protoc ,以及 micro 插件编译它,micro 插件可以帮助生成 go micro 需要的原型文件。
1 protoc --proto_path=$GOPATH /src:. --micro_out=. --go_out=. proto/greeter.proto
查看下 greeter 目录,可以看到 proto 目录中生成的文件 greeter.pb.go 以及 greeter.pb.micro.go 。
1 2 3 4 5 6 7 greeter ├── go.mod ├── go.sum └── proto ├── greeter.pb.go ├── greeter.pb.micro.go └── greeter.proto
编写服务
首先编辑greeter的服务代码 main.go 文件
主要功能:
定义并实现Greeter Handler中的接口
初始化 micro.Service
注册 Greeter Handler
运行服务
main.go 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package mainimport ( "context" "fmt" micro "github.com/micro/go-micro/v2" proto "github.com/eopenio/greeter/proto" ) type Greeter struct {}func (g *Greeter) Hello (ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { rsp.Greeting = "Hello " + req.Name return nil } func main () { service := micro.NewService( micro.Name("greeter" ), micro.Version("v0.0.1" ), ) service.Init() proto.RegisterGreeterHandler(service.Server(), new (Greeter)) if err := service.Run(); err != nil { fmt.Println(err) } }
查看下 greeter 目录,可以看到新增 main.go 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 greeter ├── go.mod ├── go.sum ├── main.go └── proto ├── greeter.pb.go ├── greeter.pb.micro.go └── greeter.proto ``` ### 运行服务 ``` bash # go run main.go 2020-03-22 20:57:40 level=info Starting [service] greeter 2020-03-22 20:57:40 level=info Server [grpc] Listening on [::]:65461 2020-03-22 20:57:40 level=info Registry [etcd] Registering node: greeter-45fc8d75-1db5-48f0-8f5d-71a691e5c982
通过 micro 命令进行查看服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # micro list services greeter # micro get service greeter service greeter version v0.0.1 ID Address Metadata greeter-45fc8d75-1db5-48f0-8f5d-71a691e5c982 192.168.3.5:65461 transport=grpc,broker=eats,protocol=grpc,registry=etcd,server=grpc Endpoint: Greeter.Hello Request: { name string } Response: { greeting string }
定义客户端 新增客户端代码 cli.go 文件。
cli.go 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package mainimport ( "context" "fmt" micro "github.com/micro/go-micro/v2" proto "github.com/eopenio/greeter/proto" ) func main () { service := micro.NewService(micro.Name("greeter.client" )) service.Init() greeter := proto.NewGreeterService("greeter" , service.Client()) rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "World" }) if err != nil { fmt.Println(err) } fmt.Println(rsp.Greeting) }
1 2 3 4 5 6 7 8 9 greeter ├── cli.go ├── go.mod ├── go.sum ├── main.go └── proto ├── greeter.pb.go ├── greeter.pb.micro.go └── greeter.proto
运行客户端 1 2 # go run cli.go Hello World
备注
本文示例可以通过以下命令,进行编译.