Golang|Golang 微服务框架——Micro的使用

一、简单介绍 Go Micro是一个插件化的基础框架,基于此可以构建微服务。Micro的设计哲学是『可插拔』的插件化架构。在架构之外,它默认实现了consul作为服务发现,通过http进行通信,通过protobuf和json进行编解码。
二、示例 为了更为直观,先从示例开始。
1、环境搭建(安装依赖)
(1)安装protobuf
具体内容参考:https://blog.csdn.net/weixin_42117918/article/details/88920221
(2)安装go-micro

go get github.com/micro/go-micro

(3)安装micro
go get github.com/micro/micro

(4)安装consul
由于Micro的服务发现并没有自己实现,仅仅是提供Plugin来接入第三方服务发现(consul, etcd), 默认使用的是consule,因此需要安装consul。(以Windows开发环境为例)
下载consul:https://www.consul.io/downloads.html
Golang|Golang 微服务框架——Micro的使用
文章图片

在安装的位置解压得到 consul.exe 文件(我的解压位置是:C:\consul)
设置环境变量:
Golang|Golang 微服务框架——Micro的使用
文章图片

启动:
cmd 命令窗口执行:consul agent -dev
consul 自带 UI 界面,打开网址:http://localhost:8500 ,可以看到当前注册的服务界面
2、创建一个proto文件
我定义的文件名为:hello.proto
syntax = "proto3"; message HelloRequest { string name = 1; } message HelloResponse { string greeting = 2; } service Greeter { rpc Hello(HelloRequest) returns (HelloResponse) {} }

3、生成xx.pb.go、xx.micro.go文件
(1)命令及生成的代码如下:
protoc --go_out=plugins=micro:. hello.proto

// Code generated by protoc-gen-go. DO NOT EDIT. // source: hello.protopackage helloimport ( fmt "fmt" proto "github.com/golang/protobuf/proto" math "math" )// Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf// This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto packagetype HelloRequest struct { Namestring`protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized[]byte`json:"-"` XXX_sizecacheint32`json:"-"` }func (m *HelloRequest) Reset(){ *m = HelloRequest{} } func (m *HelloRequest) String() string { return proto.CompactTextString(m) } func (*HelloRequest) ProtoMessage(){} func (*HelloRequest) Descriptor() ([]byte, []int) { return fileDescriptor_61ef911816e0a8ce, []int{0} }func (m *HelloRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HelloRequest.Unmarshal(m, b) } func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) } func (m *HelloRequest) XXX_Merge(src proto.Message) { xxx_messageInfo_HelloRequest.Merge(m, src) } func (m *HelloRequest) XXX_Size() int { return xxx_messageInfo_HelloRequest.Size(m) } func (m *HelloRequest) XXX_DiscardUnknown() { xxx_messageInfo_HelloRequest.DiscardUnknown(m) }var xxx_messageInfo_HelloRequest proto.InternalMessageInfofunc (m *HelloRequest) GetName() string { if m != nil { return m.Name } return "" }type HelloResponse struct { Greetingstring`protobuf:"bytes,2,opt,name=greeting,proto3" json:"greeting,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized[]byte`json:"-"` XXX_sizecacheint32`json:"-"` }func (m *HelloResponse) Reset(){ *m = HelloResponse{} } func (m *HelloResponse) String() string { return proto.CompactTextString(m) } func (*HelloResponse) ProtoMessage(){} func (*HelloResponse) Descriptor() ([]byte, []int) { return fileDescriptor_61ef911816e0a8ce, []int{1} }func (m *HelloResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HelloResponse.Unmarshal(m, b) } func (m *HelloResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_HelloResponse.Marshal(b, m, deterministic) } func (m *HelloResponse) XXX_Merge(src proto.Message) { xxx_messageInfo_HelloResponse.Merge(m, src) } func (m *HelloResponse) XXX_Size() int { return xxx_messageInfo_HelloResponse.Size(m) } func (m *HelloResponse) XXX_DiscardUnknown() { xxx_messageInfo_HelloResponse.DiscardUnknown(m) }var xxx_messageInfo_HelloResponse proto.InternalMessageInfofunc (m *HelloResponse) GetGreeting() string { if m != nil { return m.Greeting } return "" }func init() { proto.RegisterType((*HelloRequest)(nil), "HelloRequest") proto.RegisterType((*HelloResponse)(nil), "HelloResponse") }func init() { proto.RegisterFile("hello.proto", fileDescriptor_61ef911816e0a8ce) }var fileDescriptor_61ef911816e0a8ce = []byte{ // 130 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x52, 0xe2, 0xe2, 0xf1, 0x00, 0x71, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x84, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0xc0, 0x6c, 0x25, 0x6d, 0x2e, 0x5e, 0xa8, 0x9a, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x21, 0x29, 0x2e, 0x8e, 0xf4, 0xa2, 0xd4, 0xd4, 0x92, 0xcc, 0xbc, 0x74, 0x09, 0x26, 0xb0, 0x42, 0x38, 0xdf, 0xc8, 0x98, 0x8b, 0xdd, 0x1d, 0xc4, 0x4e, 0x2d, 0x12, 0xd2, 0xe0, 0x62, 0x05, 0xeb, 0x13, 0xe2, 0xd5, 0x43, 0xb6, 0x43, 0x8a, 0x4f, 0x0f, 0xc5, 0x38, 0x25, 0x86, 0x24, 0x36, 0xb0, 0x63, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x83, 0xc3, 0x7d, 0x9b, 0x00, 0x00, 0x00, }

(2)命令及生成的代码如下:
protoc --proto_path=. --micro_out=. --go_out=. hello.proto

// Code generated by protoc-gen-micro. DO NOT EDIT. // source: hello.protopackage helloimport ( fmt "fmt" proto "github.com/golang/protobuf/proto" math "math" )import ( context "context" client "github.com/micro/go-micro/client" server "github.com/micro/go-micro/server" )// Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf// This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package// Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ client.Option var _ server.Option// Client API for Greeter servicetype GreeterService interface { Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error) }type greeterService struct { cclient.Client name string }func NewGreeterService(name string, c client.Client) GreeterService { if c == nil { c = client.NewClient() } if len(name) == 0 { name = "greeter" } return &greeterService{ c:c, name: name, } }func (c *greeterService) Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error) { req := c.c.NewRequest(c.name, "Greeter.Hello", in) out := new(HelloResponse) err := c.c.Call(ctx, req, out, opts...) if err != nil { return nil, err } return out, nil }// Server API for Greeter servicetype GreeterHandler interface { Hello(context.Context, *HelloRequest, *HelloResponse) error }func RegisterGreeterHandler(s server.Server, hdlr GreeterHandler, opts ...server.HandlerOption) error { type greeter interface { Hello(ctx context.Context, in *HelloRequest, out *HelloResponse) error } type Greeter struct { greeter } h := &greeterHandler{hdlr} return s.Handle(s.NewHandler(&Greeter{h}, opts...)) }type greeterHandler struct { GreeterHandler }func (h *greeterHandler) Hello(ctx context.Context, in *HelloRequest, out *HelloResponse) error { return h.GreeterHandler.Hello(ctx, in, out) }

Golang|Golang 微服务框架——Micro的使用
文章图片

生成的文件如上图所示。
4、服务端代码
package mainimport ( "fmt" "github.com/micro/go-micro" "golang.org/x/net/context" ) import pb "MyMicro" //import proto生成的类type Greeter struct { }/* 实现proto生成的hello.micro.go中的 type GreeterHandler interface { Hello(context.Context, *HelloRequest, *HelloResponse) error} */ func (g *Greeter) Hello(ctx context.Context, rep *pb.HelloRequest, rsp *pb.HelloResponse) error { rsp.Greeting = "Hello" + rep.Name //fmt.Printf() return nil } func main() { //新建一个服务 service := micro.NewService(micro.Name("greeter"), micro.Version("latest"), micro.Metadata(map[string]string{"type": "hello world"})) service.Init()//初始化服务 err := pb.RegisterGreeterHandler(service.Server(), new(Greeter)) //注册服务 if err != nil { fmt.Println("注册服务出现了问题...", err) return } //运行服务 if err := service.Run(); err != nil { fmt.Println("服务运行出现了错误:", err) } }

5、客户端代码
package mainimport ( pb "MyMicro" "fmt" "github.com/micro/go-micro" "golang.org/x/net/context" )func main() { service := micro.NewService(micro.Name("greeter"), micro.Version("latest"), micro.Metadata(map[string]string{"type": "hello world"})) service.Init() greeter := pb.NewGreeterService("greeter", service.Client()) //调用proto生成的hello.micro.go中的NewGreeterService方法 res := pb.HelloRequest{} res.Name = "jiangzhou" rsp, err := greeter.Hello(context.TODO(), &res) //Client API for Greeter service if err != nil { fmt.Println("请求服务出现了问题...", err) return } fmt.Println("服务返回的结果为:", rsp.Greeting)}

6、运行 (1)启动consul:consul agent -dev(Windows命令行命令 )
(2)运行服务器端:
Golang|Golang 微服务框架——Micro的使用
文章图片

(3)运行客户端端:
Golang|Golang 微服务框架——Micro的使用
文章图片

三、原理 【Golang|Golang 微服务框架——Micro的使用】参考:https://blog.csdn.net/weixin_42117918/article/details/89148666

    推荐阅读