Golang 微服务框架——Micro的使用 - Go语言中文社区

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

在安装的位置解压得到 consul.exe 文件(我的解压位置是:C:consul)

设置环境变量:

启动:

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.proto

package hello

import (
	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 package

type HelloRequest struct {
	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `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.InternalMessageInfo

func (m *HelloRequest) GetName() string {
	if m != nil {
		return m.Name
	}
	return ""
}

type HelloResponse struct {
	Greeting             string   `protobuf:"bytes,2,opt,name=greeting,proto3" json:"greeting,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `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.InternalMessageInfo

func (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.proto

package hello

import (
	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 service

type GreeterService interface {
	Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error)
}

type greeterService struct {
	c    client.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 service

type 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)
}

生成的文件如上图所示。

4、服务端代码

package main

import (
	"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 main

import (
	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)运行服务器端:

(3)运行客户端端:

三、原理

参考:https://blog.csdn.net/weixin_42117918/article/details/89148666

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_42117918/article/details/89140422
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-13 12:11:48
  • 阅读 ( 1862 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢