大家好,我是木川
本文将演示如何从 0 到 1 使用 go-micro 框架实现 RPC 微服务,包括服务端和客户端,客户端发送一个名字到服务端,服务端返回问候语。
一、创建项目
创建项目目录,使用 go mod 初始化
mkdir goexamples
go mod init goexamples
如果当前项目在 GOPATH 目录之外,记得设置
go env -w GO111MODULE=on
目录结构如下:
proto/greeter.proto: 接口定义代码 client.go: 客户端代码 server.go: 服务端代码
一、编写 Proto 文件
go-micro 框架 使用 gRPC 进行 远程过程调用,而 gRPC 使用 Google 开发的数据交换格式和接口定义语言:Protobuf (Protocol Buffers)在不同服务之间进行数据通信、序列化和反序列化。
所以需要编写 Protobuf 文件来定义 Request、Response、Interface,文件扩展名 为 .proto ,用于定义数据结构和消息格式。
编写 greeter.pb 文件,内容如下:
// Proto文件使用的协议版本,新项目建议采用proto3
syntax = "proto3";
// 分号前面是包路径(根据包路径自动创建目录),后面是包名
option go_package = "../proto;proto";
// 定义接口
service Greeter {
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
// 定义输入参数
message HelloRequest {
string name = 1;
}
// 定义输出参数
message HelloResponse {
string msg = 1;
}
这段代码是一个简单的示例,用于定义一个名为 "Greeter" 的微服务,该服务包含一个 "Hello" RPC 方法,用于问候。"Request" 和 "Response" 消息定义了方法的输入和输出。
这个Proto文件可以用来生成不同编程语言的代码,以便在客户端和服务端之间实现消息的序列化和反序列化以及RPC通信。
二、生成 Proto Go 代码
要根据 Proto 文件生成 Go 代码,你需要使用 Protobuf 编译器 protoc
以及 Go 的 Protobuf 插件。以下是生成 Go 代码的步骤:
安装 Protobuf 编译器 protoc
前往 Protocol Buffers 的 GitHub Release 页面 https://github.com/protocolbuffers/protobuf/releases,选择适合你操作系统的最新 protoc 版本并下载安装,mac 可以直接用 brew install protobuf 安装
安装完成后,你可以在终端中运行以下命令来验证 protoc 是否成功安装,如果 protoc 成功安装,它将显示安装的版本号
protoc --version
安装 protoc-go
Go 的 Protobuf 插件允许你从 Proto 文件生成 .go 代码,默认会安装到$GOPATH/go/bin目录下
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
安装 protoc-gen-micro
go-micro 框架 protoc-gen-micro 插件 允许你从 Proto 文件生成 .micro.go 代码,默认会安装到$GOPATH/go/bin目录下
go install github.com/go-micro/generator/cmd/protoc-gen-micro@latest
生成 Go 代码
使用 protoc
编译器来生成 Go 代码,假设你有一个名为 greeter.proto
的 Proto 文件,并且你希望生成 Go 代码。cd 到 proto
目录,在终端中执行以下命令:
protoc --go_out=. --micro_out=. greeter.proto
--go_out
指定了生成 .go 代码的目标目录,这里使用当前目录(".")--micro_out
指定了生成 .micro.go 代码的目标目录,这里使用当前目录(".")greeter.proto
是你的 Proto 文件名
运行上述命令后,你将在当前目录下看到生成的 Go 代码文件,包括消息结构和序列化/反序列化方法。生成的文件名称将与你的 .proto
文件名称相对应,但会使用 ".pb.go" 作为扩展名。
如果你的 .proto
文件名为 greeter.proto
,则生成的 Go 代码文件将是 greeter.pb.go
。
如果遇到下面这个错误,则需要将 $GOPATH/bin 加入到 path 环境变量
protoc-gen-micro: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
vim ~/.bash_profile
export PATH=$PATH:/Users/mc/go/bin // 替换这里的GOPATH目录,比如我的是/Users/mc/go
source ~/.bash_profile
三、编写服务端代码
编写server.go
,用于实现服务端:
package main
import (
"context"
"log"
pb "goexamples/proto" // proto 接口定义
"go-micro.dev/v4" // 引入 go-micro 框架
)
// 定义 Greeting 服务
type GreetingService struct{}
// 实现 proto 接口定义 的 Greeting 服务
func (s *GreetingService) Hello(ctx context.Context, req *pb.HelloRequest, rsp *pb.HelloResponse) error {
rsp.Msg = "Hello, " + req.Name
return nil
}
func main() {
// 创建微服务实例
service := micro.NewService(
micro.Name("greeter"),
)
// 接收命令行参数 如--server_address
service.Init()
// 注册 Greeting 服务
pb.RegisterGreeterHandler(service.Server(), new(GreetingService))
// 运行微服务
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
四、编写客户端代码
编写client.go
,用于实现客户端:
package main
import (
"context"
"fmt"
pb "goexamples/proto"
"go-micro.dev/v4"
)
func main() {
// 创建微服务实例
service := micro.NewService()
// 接收命令行参数 如--server_address
service.Init()
// 创建 Greeting 客户端存根
cl := pb.NewGreeterService("greeter", service.Client())
// 发送请求
rsp, err := cl.Hello(context.Background(), &pb.HelloRequest{
Name: "muchuang",
})
if err != nil {
fmt.Println(err)
return
}
fmt.Println(rsp.Msg)
}
五、编译和运行
现在,你可以使用以下命令编译和运行服务端和客户端:
# 下载代码库依赖
go get go-micro.dev/v4
go mod tidy
# 编译服务端
go build -o server server.go
# 编译客户端
go build -o client client.go
# 运行服务端
./server
# 在另一个终端中运行客户端
./client
客户端将发送一个名字到服务端,服务端将返回一个问候语,客户端会打印出这个问候语。这是一个简单的Go-Micro微服务示例,演示了微服务之间的通信。请确保根据你的项目需要和Proto文件定义进行适当的修改。
六、参考
micro 代码生成器:https://github.com/go-micro/generator
go-micro 框架:https://github.com/go-micro/examples/tree/main/greeter
最后给自己的原创 Go 面试小册打个广告,如果你从事 Go 相关开发,欢迎扫码购买,目前 10 元买断,加下面的微信发送支付截图额外赠送一份自己录制的 Go 面试题讲解视频
如果对你有帮助,帮我点一下在看或转发,欢迎关注我的公众号