Go Micro是一个微服务开发框架。Go Micro提供了分布式系统开发的核心要求,包括RPC和事件驱动的通信。
consul
是Go Micro
默认的服务发现注册中心。发现系统可插拔,其他插件像etcd
,kubernetes
,zookeeper
。content-type
)动态编码消息。客户端和服务端会一起使用content-type
格式来对Go进行无缝编/解码。content-type
默认包含proto-rpc
和json-rpc
。RPC
通信基于支持双向流的请求/响应方式,提供同步通信机制,请求发送到服务时,会自动解析,负载均衡,拨号,转成字节流。Go Micro
为每个分布式系统抽象出接口,因此,Go Micro
的接口都是可插拔的,允许其在运行时不可知的情况下仍可支持。微服务中有个关键需求点,就是接口的强定义。Micro使用protobuf来完成这个需求。以gRPC使用简介文章中的服务为例,定义Greeter处理器,它有一个Hello方法。它有HelloRequest入参对象以及HelloResponse出参对象,两个对象都有一个字符串类型的参数。
helloworld.proto
文件:
syntax = "proto3";
package main;
service Greeter {
rpc Hello (HelloRequest) returns (HelloResponse) {
}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 2;
}
在定义好原型后,我们使用protoc
以及micro
的插件来编译它,micro插件可以帮助生成go micro
需要的原型文件。
protoc --proto_path=. --micro_out=. --go_out=. ./helloworld.proto
执行完命令后,将会在当前目录下生成helloworld.pb.go
文件和helloworld.micro.go
文件。
其中helloworld.micro.go
文件中分别定义了Greeter
服务的客户端API和服务端API,如下:
...
// Client API for Greeter service
type GreeterService interface {
Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error)
}
// Server API for Greeter service
type GreeterHandler interface {
Hello(context.Context, *HelloRequest, *HelloResponse) error
}
下方的代码是greeter服务的代码,它要实现下面的几个要求:
greeter_servermicro.go
文件内容:
package main
import (
"context"
"fmt"
"github.com/micro/go-micro"
)
type Greeter struct {
}
func (g *Greeter) Hello(ctx context.Context, req *HelloRequest, rsp *HelloResponse) error {
rsp.Greeting = "hello" + req.Name
return nil
}
func main() {
// 创建新的服务,这里可以传入其他选项
service := micro.NewService(micro.Name("greeter"))
// 初始化方法会解析命令行标识
service.Init()
// 注册处理器
err := RegisterGreeterHandler(service.Server(), new(Greeter))
if err != nil {
fmt.Println("failed to register a greeter handler: ", err)
}
// 运行服务
if err = service.Run(); err != nil {
fmt.Println("failed to run a service: ", err)
}
}
执行命令go run greeter_servermicro.go
。
输出
2019/04/29 13:39:41 Transport [http] Listening on [::]:54648
2019/04/29 13:39:41 Broker [http] Connected to [::]:54649
2019/04/29 13:39:41 Registry [mdns] Registering node: greeter-29622a6a-50b6-4ff9-b580-8ce1b7a52f5f
下面的客户端代码用来查询greeter服务,上面我们生成的proto原型文件中包含了客户端部分,这样可以减少模板代码量。
greeter_clientmicro.go
文件
package main
import (
"context"
"fmt"
"github.com/micro/go-micro"
)
func main() {
// 定义服务,可以传入其他可选参数
service := micro.NewService(micro.Name("greeter.client"))
service.Init()
// 创建新的客户端
greeter := NewGreeterService("greeter", service.Client())
// 调用greeter
rsp, err := greeter.Hello(context.TODO(), &HelloRequest{Name: "benben_2015"})
if err != nil {
fmt.Println("failed to execute a greeter: ", err)
}
// 打印响应请求
fmt.Println(rsp.Greeting)
}
执行命令go run greeter_clientmicro.go
输出
hello benben_2015
Go Micro
包含了函数式编程模型。Function是指接收一次请求,执行后便退出的服务。
greeter_funcmicro.go
文件内容:
package main
import (
"context"
"fmt"
"github.com/micro/go-micro"
)
type Greeter struct {
}
func (g *Greeter) Hello(ctx context.Context, req *HelloRequest, rsp *HelloResponse) error {
rsp.Greeting = "hello" + req.Name
return nil
}
func main() {
// 创建新函数
fnc := micro.NewFunction(micro.Name("greeter"))
// 初始化命令行
fnc.Init()
// 注册handler
err := fnc.Handle(new(Greeter))
if err != nil {
fmt.Println("failed to register a handler: ", err)
}
// 运行服务
if err = fnc.Run(); err != nil {
fmt.Println("failed to run a service: ", err)
}
}
参考文章