Go语言微服务实战之micro微服务框架

之前的文章我们大致了解了微服务,同时我们还准备好了一台搭载CentOS系统的云服务器,这篇文章我们正式开始微服务的实践之旅。

一提到微服务,首先想到的就是Spring Cloud,阿里的Dubbo等。与go语言相比,java的一个巨大优势就是生态系统非常成熟,有很多成熟的商业级框架可供使用,go相对而言比较新,因此生态上还不如java那么完善,但是这并不妨碍我们学习微服务,在github上已经有一些开源的go微服务框架可以使用,比如go micro,go kit,go chassis等,这里我们选择go micro,在写这篇文章的时候,这个开源微服务框架在github上已经有多达12.9K的Star数,一个微服务框架该有的东西基本上全都具备了,是入门微服务非常不错的一个开源项目。

1、认识micro微服务框架

如果想深入学习,最好的方法是先荡一份源码研究,go micro的主页:

https://github.com/micro/go-micro

初学者可以先不急着一上来就去挖原理,先学会如何使用,然后在循序渐进,建议初学者先点开下面的链接仔细看一遍文档:

https://micro.mu/docs/framework.html

micro满足分布式系统开发的核心需求,在设计上采用插件化的方式,一些核心功能诸如消息中间件、服务注册及发现等都是可插拔的,micro提供默认实现,但是开发者可以根据自己的需求随意替换。

我们来看看micro的主要特点:

(1) 服务发现:micro支持自动化的服务发现和域名解析。服务发现在微服务开发中处于核心地位,正如我们在第一篇文章所说,当微服务独立部署在不同机器上的时候,服务A想要和服务B通信就必须要知道服务B所在的机器。micro提供了基于mDNS的服务发现的默认实现,当然你可以使用其他插件甚至自己编写插件来满足自己的需求。

(2) 负载均衡:通常一个商业级的应用,因为用户量较大,一些核心服务往往会部署在多台机器上,这就涉及到负载均衡的问题,大量的请求不能落地到某一台机器上,而是用某种负载均衡策略分摊到所有的机器上去。micro提供了基于随机哈希的负载均衡策略,当发现某台机器有问题时会选择另外一台机器进行重试。

(3) RPC:micro对同步通信进行了抽象,客户端到服务端的请求会被自动解析并做负载均衡,默认采用gRPC做为RPC通道。

(4) 异步消息:micro支持消息的发布-订阅,这个也是可插拔的,你可以用Kafka,RabbitMQ等任何你熟悉的消息中间件发送异步消息。

(5) 插件化:诸如服务发现、负载均衡、消息中间件等这些分布式系统开发中的核心组件,micro都做了抽象,可以根据自己的需求实现接口去替换,当然社区也已经有很多现成的插件供开发者使用。

2、Hello,Micro

这一节,我们就用经典的Hello world的方式来看看如何编写一个最简单的微服务。

2.1 开发环境

我们假定读者已经是go语言的开发者,这个系列的文章我们不会介绍go语法相关的知识。我们以GoLand IDE为例。

go版本1.14,GoLand版本2020.1.2

首先,新建一个工程,建好之后在GoLand中开启go module,并且添加环境变量:GOPROXY = https://goproxy.cn,在Mac上可以通过Preferences -> Go Modules来设置:

2.2 初始化模块

我们在工程中新建一个模块micro,新建一个文件夹micro,然后命令行:

go mod init micro

然后我们会在项目根目录下看到一个go.mod的文件文件。

2.3 编写协议文件

micro是基于google protobuf的,因此我们需要先编写.proto的协议文件:

syntax = "proto3";

package pb;

// 定义微服务对外提供的接口
service Greeter {

    rpc Hello(Request) returns (Response) {}
}

// 请求
message Request {
    string name = 1;
}

// 响应
message Response {
    string msg = 1;
}

是不是很简单,你的服务想提供什么能力,就用接口定义出来(包括参数等),我们在项目中新建一个proto目录,将协议文件放在这里,目录结构如下,其中pbfile目录存放.proto,pb目录则保存生成的代码:

接下来我们需要根据这份.proto协议生成代码,为了生成micro特定的代码,需要先在开发机上安装protobuf以及一些相关工具:

brew install protobuf
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get github.com/micro/micro/v2/cmd/protoc-gen-micro@master

所有必须的工具都安装好之后,在命令行敲入命令来生成代码: 

protoc --proto_path=$GOPATH/src:./proto/pbfile --go_out=./proto/pb --micro_out=./proto/pb hello.proto

--proto_path指定了要在哪些目录中寻找.proto协议文件,--go_out和--micro_out指定了文件的输出目录。

2.4 编写微服务

终于到了手撕第一个微服务的时刻了,因为功能非常简单,我们直接上代码,相信大家都能秒懂实在不懂的也没关系,复制到IDE里先运行起来也可以。在项目中新建server/main目录,在此目录下新建main.go,把以下代码复制进去:

package main

import (
	"context"
	"fmt"
	"github.com/micro/go-micro/v2"
	"micro/proto/pb"
)

type Greeter struct {}

func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error  {
	//把客户端的请求回射给客户端
	rsp.Msg = req.Name
	return nil
}

func main() {

	// 新创建一个服务,服务名为greeter,服务注册中心会用这个名字来发现服务
	service := micro.NewService(
		micro.Name("greeter"),
	)

	// 初始化
	service.Init()

	// 注册处理器
	pb.RegisterGreeterHandler(service.Server(), new(Greeter))

	// 启动服务运行
	if err := service.Run(); err != nil {
		fmt.Println(err)
	}
}

总结一下主要的点:

(1) 定义结构体,实现协议文件中定义的接口;

(2) 使用micro.NewService创建一个微服务,必须要指定一个服务名,如果一个系统有多个微服务,请注意不要重名,这个名字是用来做服务发现用的;

(3) 将我们实现了协议接口的结构体注册到micro;

(4) 最后启动服务运行;

现在,我们运行一下试试,在终端使用go run server/main/main.go运行程序,可以看到以下输出:

从控制台输出的日志中可以看到服务使用grpc,在54836端口上监听请求,同时可以看到我们在mdns上注册了一个节点,这样客户端就能通过mdns发现我们的微服务并调用接口。此前我们说过micro的服务发现与注册中心是可以通过插件化的方式替换的,在后续的文章中我们会用kubernetes做为服务注册中心,替换micro默认的mdns。

2.5 编写客户端

最后我们写个客户端程序来调用上面的微服务,在项目中新建client/main目录,在此目录下新建main.go文件,把以下代码拷贝过去:

package main

import (
	"context"
	"fmt"
	"github.com/micro/go-micro/v2"
	"micro/proto/pb"
)

func main() {

	// 创建一个服务
	service := micro.NewService(micro.Name("greeter.client"))
	// 初始化
	service.Init()
	// 创建一个微服务的客户端
	greeter := pb.NewGreeterService("greeter", service.Client())
	// 调用微服务
	rsp, err := greeter.Hello(context.TODO(), &pb.Request{Name: "Hello Micro"})
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(rsp.Msg)
}

同样我们先创建并初始化一个客户端服务,注意名字与服务端不同,然后调用服务接口,并在控制台打印服务的响应,在终端运行该程序,在控制台上看到以下输出:

如果你顺利完成了这一步,那么恭喜,你已经开发出了自己的第一个微服务,虽然它几乎什么也没有做。

2.6 使用micro来运行微服务

前面我们在自己的开发机上本地编译运行微服务,我们还可以用micro工具集来启动微服务,micro有一套完备的工具集供我们使用,我们先安装一下:

go install github.com/micro/micro/v2

安装完成以后,我们来尝试运行一下刚才的服务:

在终端运行:

micro server

然后,在打开一个终端,运行:

micro run server/main/

指定我们的微服务代码所在的目录即可,此时可以在终端看到以下输出:

我们用micro工具集一样运行起了我们的微服务。

然后我们利用工具来查看一下有哪些服务,在终端敲以下命令:

micro list services

输出如下:

可以看到默认已经启动了不少的服务,我们的greeter服务位于最下面。

现在查看一下这个服务的详细信息,在终端键入下面的命令:

micro get service greeter

看到以下输出:

详细信息一目了然。

最后咱们试着调用一下:

这次我们得到了JSON格式的输出。

3、总结

这篇文章我们实操了第一个微服务例子,并用不同的方式运行了它,完整的跑通这个简单的示例后,相信你对微服务的认识又进了一步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章