服务发现是每个分布式系统都需要解决的问题,go-micro将这个任务抽象到一个接口中,github.com/micro/go-micro/v2/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, ...DeregisterOption) error
GetService(string, ...GetOption) ([]*Service, error)
ListServices(...ListOption) ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
所有实现这个结构的插件都可以作服务发现的角色。事实上,在go-plugins上已经有很过实现,包括主流的etcd/consul/zookeeper。以及在内存中的轻量实现。默认实现基于mdns,无需配置,开箱即用。
异步消息是构建松耦合与健壮系统的关键技术,相应的接口:
github.com/micro/go-micro/v2/broker/Broker
// Broker is an interface used for asynchronous messaging.
type Broker interface {
Init(...Option) error
Options() Options
Address() string
Connect() error
Disconnect() error
Publish(topic string, m *Message, opts ...PublishOption) error
Subscribe(topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)
String() string
}
已经有一些插件,包括RabbitMQ, Kafka, NSQ, etc,默认使用HTTP,无需设置。
编解码器接口定义了消息编码与解码格式,github.com/micro/go-micro/v2/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等
定义微服务接口
// Server is a simple micro server abstraction
type Server interface {
// Initialise options
Init(...Option) error
// Retrieve the options
Options() Options
// Register a handler
Handle(Handler) error
// Create a new handler
NewHandler(interface{}, ...HandlerOption) Handler
// Create a new subscriber
NewSubscriber(string, interface{}, ...SubscriberOption) Subscriber
// Register a subscriber
Subscribe(Subscriber) error
// Start the server
Start() error
// Stop the server
Stop() error
// Server implementation
String() string
}
// Transport is an interface which is used for communication between
// services. It uses connection based socket send/recv semantics and
// has various implementations; http, grpc, quic.
type Transport interface {
Init(...Option) error
Options() Options
Dial(addr string, opts ...DialOption) (Client, error)
Listen(addr string, opts ...ListenOption) (Listener, error)
String() string
}
abstracts logic of service selection. you can implement various load balancing strategies with this interface
// Wrapper wraps a client and returns a client
type Wrapper func(Client) Client
最快速的构建micro服务模板的方法是使用micro命令行工具
GO111MODULE=on go get github.com/micro/micro/v2@v2.4.0
then
micro new hello --namespace=com.foo --gopath=false
目录结构
luslin@local:~/go/workspace/tools/micro-hello$ tree
.
├── Dockerfile
├── generate.go
├── go.mod
├── go.sum
├── handler
│ └── micro.go
├── main.go
├── Makefile
├── plugin.go
├── proto
│ └── micro
│ └── micro.proto
├── README.md
└── subscriber
└── micro.go
在micro-hello/proto/micro 目录下只有定义的proto文件,没有生成文件,需要执行
protoc --proto_path=. --micro_out=. --go_out=. micro.proto
生成文件micro.pb.go、micro.pb.micro.go
需要安装protoc、protoc-gen-go、protoc-gen-micro
protoc-gen-micro安装:
GO111MODULE=on go get -u github.com/micro/protoc-gen-micro/v2
参考
protoc安装,protoc-gen-go安装
然后修改micro-hello/main.go文件
package main
import (
"github.com/micro/go-micro/v2"
log "github.com/micro/go-micro/v2/logger"
"micro-hello/handler"
"micro-hello/subscriber"
proto "micro-hello/proto/micro" // 这里将原来的micro 修改为proto 可能与命名冲突有关
)
func main() {
// New Service
service := micro.NewService(
micro.Name("comm.foo.service.micro"), // bug,不使用我们提供的,需要修改
micro.Version("latest"),
)
// Initialise service
service.Init()
// Register Handler
proto.RegisterMicroHandler(service.Server(), new(handler.Micro)) // 这里与上面相同
// Register Struct as Subscriber
micro.RegisterSubscriber("go.micro.service.micro", service.Server(), new(subscriber.Micro))
// Run service
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
运行main.go,可以看到同时启动了rrpc与http服务
2020-05-22 10:34:42 file=auth.go:31 level=info Auth [noop] Authenticated as go.micro.service.micro-41b5434c-22cc-4846-ae0b-a76af49eedae in the go.micro namespace
2020-05-22 10:34:42 file=service.go:205 level=info Starting [service] go.micro.service.micro
2020-05-22 10:34:42 file=grpc.go:845 level=info Server [grpc] Listening on [::]:46805
2020-05-22 10:34:42 file=grpc.go:862 level=info Broker [http] Connected to 127.0.0.1:40695
2020-05-22 10:34:42 file=grpc.go:676 level=info Registry [mdns] Registering node: go.micro.service.micro-41b5434c-22cc-4846-ae0b-a76af49eedae
2020-05-22 10:34:42 file=grpc.go:711 level=info Subscribing to topic: go.micro.service.micro
有个问题是micro没有使用我们提供的命名空间,而是go.micro.service.micro, 需要我们自己修改main.go与proto文件, 将proto包名修改为package com.foo.service.micro
本文介绍了如何构建一个demo mirco project, 接下来将会介绍micro的更多特性,并且改变它的默认行为