Micro实践(一)

Micro是一组工具,可帮助开发人员构建和管理微服务

它包含两个部分:

  1. go-micro:Golang微服务开发框架。这是核心。通过利用它,开发人员可以快速构建微服务。这些微服务的典型类型是gRPC。
  2. micro:命令行工具。尽管不是强制性的,但它为Micro的开发和管理提供了很多便利。例如,模板项目生成,运行时状态检查和服务调用。该工具也基于 go-micro。

另外,在大多数情况下,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构建gRPC服务

入门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]

证明微服务已经可以使用。


欢迎转载,本文地址: https://blog.prodrich.com/detail/13/

带着使命来到世上的你,给他人提供价值,才有价值