一、框架简介
go-micro是一个可插拔的,用于构建微服务的基础框架,提供了分布式开发所需的核心组件,包括RPC和事件驱动通信等。其设计哲学是可插拔的插件式架构,通过提供组件工具,明确微服务开发的边界,让我们专注于开发业务本身。
二、go-micro 架构介绍
go-micro 之所以可以灵活订制和它的框架结构是分不开的,go-micro 由 8 个关键的 interface 组成,每一个 interface 都可以根据自己的需求重新实现。这 8 个主要的 interface 也构成了 go-micro 的框架结构:
- 最顶层的service,是构建服务的主要组件,代表一个微服务;Service封装了下面的客户端Client和服务器端Server作为其底层支撑。
- Client是请求服务的接口,从Register中获取Server信息,然后封装了
Transport和Codec进行RPC调用,也封装了Broker进行消息发布;默认通过RPC协议进行通信,也可以基于HTTP或gRPC; - Server用于构建微服务的接口,也将以接收
Broker推送过来的消息;需要向Register注册自己的服务信息,以便客户端发起请求,默认通过RPC协议通信,也可替换为HTTP或给gRPC - Broker 是消息发布/订阅的接口,默认实现是基于
HTTP,在生产环境可以替换为Kafka、RabbitMQ等其他组件实现; Codec用于编码/解码消息。默认为protobuf,支持的格式包括json、bson、msgpack等。- Register用于实现服务的注册和发现,当新的service启动时,需要向Register注册,然后
Registry通知客户端进行更新。然后默认是mdns,但常基于Consul实现服务服务注册和发现,也可以改为etcd,kubernetes等。 Selecter选择器是实现go-micro负载均衡,是客户端负载均衡;当客户端向服务器发出调用时,首先向注册中心查询,并获取所需的服务清单,选择器将选择服务清单中的一个用于调用。目前实现的负载均衡算法有循环算法和随机算法,默认使用随机算法。Transport是服务之间通信的接口,也就是服务发送和接收的最终实现方式,默认使用HTTP同步通信,也可以支持TCP、UDP、NATS、gRPC等其他方式。
各个组件接口之间的关系如下图:
三、快速入门
1、准备工作
(1) 安装protobuf编译器protoc,可从 protobuf 的github仓库查看最新版本,下载适合自己系统的版本,然后解压protoc放入/usr/local/bin目录下。
检查是否安装成功,命令如下
$ protoc --version
libprotoc 23.4
(2)安装protoc插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
(3) go-micro工具集
go get go-micro.dev/v4@latest
go install github.com/go-micro/cli/cmd/go-micro@latest
go install github.com/asim/go-micro/cmd/protoc-gen-micro/v4@latest
(4) 创建目录结构
在合适的目下新建go-micro目录,用于管理go-micro相关的项目
mkdir go-micro
在go-micro目录下创建HelloWorld目录,用于编写示例
cd go-micro
mkdir helloworld
在HelloWorld目录下,创建如下目录和文件
2、编写相关代码
(1)编写proto文件定义服务和消息。
在protos/hello写入greeter.proto 文件:
syntax= "proto3";
package hello;
option go_package ="go-micro/helloworld/protos/hello";
message HelloRequest{
string name = 1;
}
message HelloResponse{
string greeting = 1;
}
service Greeter {
rpc SayHello(HelloRequest) returns (HelloResponse);
}
(2) 使用protoc生成对应的go代码。进入protos目录下,输入如下命令:
protoc --micro_out=paths=source_relative:. --go_out=paths=source_relative:. ./hello/greeter.proto
会生成 greeter.pb.go 和 greeter.pb.micro.go 两个文件。
(3) 编写业务逻辑提供服务
- 编写服务端代码:server端main.go
package main
import (
"log"
"go-micro/handler"
pb "go-micro/helloworld/protos/hello"
"go-micro.dev/v4"
)
func main() {
//创建服务并为服务命名
service := micro.NewService(
micro.Name("HelloWorld"),
)
//初始化
service.Init()
//注册handler
if err := pb.RegisterGreeterHandler(service.Server(), &handler.Greeter{}); err != nil {
log.Fatal(err)
}
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
- 编写handler。 编写handler目录下的
greeter.go文件
package handler
import (
"context"
pb "go-micro/helloworld/protos/hello"
)
type GreeterService struct{}
func (g *GreeterService) SayHello(ctx context.Context, req *pb.HelloRequest, rsp *pb.HelloResponse) error {
rsp.Greeting = "Hello " + req.Name + " welcome to micro"
return nil
}
-
编写client端调用服务
在client目录下编写main.go
package main import ( "context" "fmt" "go-micro.dev/v4" pb "go-micro/helloworld/protos/hello" ) func main() { //创建一个新的服务,并命名 service := micro.NewService( micro.Name("client"), ) service.Init() // 绑定客户端 client := pb.NewGreeterService("HelloWorld", service.Client()) rsp, err := client.SayHello(context.Background(), &pb.HelloRequest{ Name: "Kobe", }) if err != nil { panic(err) } fmt.Println(rsp.Greeting) }3、启动服务,进行调用
运行根目录下的main.go
运行client目录下main.go文件
执行效果:终端输出
GOROOT=/usr/local/go #gosetup
GOPATH=/home/wsy/go #gosetup
/usr/local/go/bin/go build -o /tmp/GoLand/___go_build_gomicro_test_client gomicro-test/client #gosetup
/tmp/GoLand/___go_build_gomicro_test_client
Hello Kobe welcome to micro
进程 已完成,退出代码为 0
四 、总结
本篇介绍了go-micro的架构和构成组件以及其特点,用go-micro实现了经典的Hello World服务,入门微服务开发。