它包含两个部分:
另外,在大多数情况下,go插件是必需的,它是一系列插件。它提供了许多不同的选择,涉及服务发现,异步消息传递和传输协议。由于go-micro被设计为插件架构,因此使用这些插件,可以实现非常灵活的组合以满足各种需求。用户可以随时开发自己的插件以进行进一步扩展。
服务发现是每个分布式系统都必须解决的问题。go-micro将此任务抽象到一个界面中
github.com/micro/go-micro/registry/Registry
// The registry provides an interface for service discovery
// and an abstraction over varying implementations
// {consul, etcd, zookeeper, ...}
type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
任何实现此接口的插件都可以扮演服务发现的角色。实际上,go-plugins中已经提供了许多实现,包括对主流产品(例如etcd / consul / zookeeper)的支持以及内存中的轻量级实现。默认实现基于多播DNS(mdns),无需进行配置,开箱即用。
异步消息传递是构建松耦合且健壮的系统的关键技术。对应的微信接口为:
github.com/micro/go-micro/broker/Broker
// The registry provides an interface for service discovery
// and an abstraction over varying implementations
// {consul, etcd, zookeeper, ...}
type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
go-plugins中已经有几个代理插件,包括RabbitMQ,Kafka,NSQ等,默认实现基于HTTP,并且不需要配置。
github.com/micro/go-micro/codec/Codec
// Codec encodes/decodes various types of messages used within go-micro.
// ReadHeader and ReadBody are called in pairs to read requests/responses
// from the connection. Close is called when finished with the
// connection. ReadBody may be called with a nil argument to force the
// body to be read and discarded.
type Codec interface {
Reader
Writer
Close() error
String() string
}
当前支持包括json / bson / msgpack等。 除了上述三个接口外,还有许多其他接口:
1. Server,定义微服务的服务器
2. Transport,定义运输协议
3. Selector,抽象服务选择逻辑。您可以通过此界面实施各种负载平衡策略
4. Wrapper,定义可以包装服务器/客户端请求的中间件
有了这个坚实的基础,开发人员可以将更多的精力放在业务逻辑开发上,而不是将精力放在繁琐的基本任务上。
入门Micro的最快方法是通过命令行工具创建模板项目micro。使用前需要先编译安装。
micro new hello --namespace=com.foo --gopath=false
命令的每个参数都有自己的含义: 1. micro new,通过运行micro命令行工具的new子命令来创建gRPC服务 2. hello,定服务名称 3. –namespace=com.foo,服务的名称空间 4. –gopath=false,不在$GOPATH生成代码,而是到当前目录中(由于Golang支持Go Module,因此新项目应放在$GOPATH之外)
执行命令后,我们将得到如下屏幕输出:
Creating service com.foo.srv.hello in hello
.
├── main.go
├── generate.go
├── plugin.go
├── handler
│ └── hello.go
├── subscriber
│ └── hello.go
├── proto/hello
│ └── hello.proto
├── Dockerfile
├── Makefile
└── README.md
download protobuf for micro:
brew install protobuf
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u github.com/micro/protoc-gen-micro
compile the proto file hello.proto:
cd hello
protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/hello/hello.proto
由于Micro使用Protobuf定义服务接口,因此我们需要首先安装与Protobuf相关的依赖项。
# install protobuf
brew install protobuf
# install protoc-gen-go
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
# install protoc-gen-micro
go get -u github.com/micro/protoc-gen-micro
注意:protoc-gen-micro不是Protobuf核心的一部分,它是Micro团队开发的Protobuf扩展,专门用于生成与Micro相关的代码。
在项目中生成了一个Makefile,其中包含一些常用任务。因此,您可以使用命令make来编译和运行项目。 该项目将使用Go Module,但micro new不会为我们自动生成go.mod,让我们生成它。
cd hello
go mod init hello
将生成一个空的go.mod,修改内容如下:
module hello
go 1.13
require github.com/micro/go-micro v1.18.0
现在我们可以编译了。
make build && ./hello-srv
屏幕输出如下:
protoc --proto_path=/Users/cuixg/go/src:. --micro_out=. --go_out=. proto/hello/hello.proto
go build -o hello-srv *.go
2020-01-10 13:51:21.627440 I | Transport [http] Listening on [::]:51564
2020-01-10 13:51:21.627541 I | Broker [http] Connected to [::]:51565
2020-01-10 13:51:21.627710 I | Registry [mdns] Registering node: com.foo.srv.hello-54151215-f985-42ab-9fe8-f92a682d332d
2020-01-10 13:51:21.629620 I | Subscribing com.foo.srv.hello-54151215-f985-42ab-9fe8-f92a682d332d to topic: com.foo.srv.hello
2020-01-10 13:51:21.629839 I | Subscribing com.foo.srv.hello-54151215-f985-42ab-9fe8-f92a682d332d to topic: com.foo.srv.hello
从屏幕输出中可以看到,首先make build运行protoc,编译.proto文件,然后运行go build,生成可执行的二进制hello-srv 最后,hello-srv已启动并准备好提供服务。
有2个坑:
1) micro的更新太快,用命令生产的proto版本不是V2,但是main.go引用的都是V2的micro,所以生产proto之后要手动修改hello.pb.micro.go源码:
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
import (
context "context"
client "github.com/micro/go-micro/v2/client"
server "github.com/micro/go-micro/v2/server"
)
里面的v2是手动加入的。
2) 如果运行make build,每次都会自动生成proto,所以就又会报错了。所以要改Makefile:
.PHONY: build
build:
go build -o microtry-srv *.go
原来在build后面有proto,意思是先生成proto文件,删掉了。
也可以不用make,直接在hello项目目录下用下面的命令编译:
go build -o hello.exe
运行起来后,如何测试接口呢?还是用micro命令:
micro call go.micro.srv.hello Hello.Call '{"name":"hello"}'
然后返回以下信息:
$ micro call go.micro.srv.hello Hello.Call '{"name":"hello"}'
{
"msg": "Hello hello"
}
从服务端看到以下输出:
level=info [Received Hello.Call request]
证明微服务已经可以使用。
带着使命来到世上的你,给他人提供价值,才有价值