您现在的位置是:首页 >学无止境 >基于protobuf构建grpc服务网站首页学无止境

基于protobuf构建grpc服务

g-Jack 2023-06-26 12:00:02
简介基于protobuf构建grpc服务

一、protobuf介绍

protobuf是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

优势:

  1. 序列化后体积相比Json和XML很小,适合网络传输

  2. 支持跨平台多语言

  3. 消息格式升级和兼容性还不错

  4. 序列化反序列化速度很快

二、安装

第一步:下载通用编译器

地址:Releases · protocolbuffers/protobuf · GitHub

根据不同的操作系统,下载不同的包,我是windows电脑,解压出来是protoc.exe

 

第二步:配置环境变量

 

 第三步:安装go专用的protoc的生成器

 

go get github.com/golang/protobuf/protoc-gen-go

安装后会在GOPATH目录下生成可执行文件,protobuf的编译器插件protoc-gen-go,执行protoc命令会自动调用这个插件

 第四步、使用protobuf

  1. 定义了一种源文件,扩展名为 .proto,使用这种源文件,可以定义存储类的内容(消息类型)

  2. protobuf有自己的编译器 protoc,可以将 .proto 编译成对应语言的文件,就可以进行使用了

四、proto样例

// 指定的当前proto语法的版本,有2和3
syntax = "proto3";
//option go_package = "path;name"; ath 表示生成的go文件的存放地址,会自动生成目录的
// name 表示生成的go文件所属的包名
option go_package="../service";
// 指定等会文件生成出来的package
package service;

message User {
  string username = 1;
  int32 age = 2;
}

 运行protoc命令编译成go中间文件

# 编译user.proto之后输出到service文件夹
protoc --go_out=../service user.proto

五、构建rpc服务

5.1 项目结构

5.2、编写protobuf文件

// 这个就是protobuf的中间文件

// 指定的当前proto语法的版本,有2和3
syntax = "proto3";
option go_package="../service";

// 指定等会文件生成出来的package
package service;

// 定义request model
message ProductRequest{
	int32 prod_id = 1; // 1代表顺序
}

// 定义response model
message ProductResponse{
	int32 prod_stock = 1; // 1代表顺序
}

// 定义服务主体
service ProdService{
    // 定义方法
    rpc GetProductStock(ProductRequest) returns(ProductResponse);
}

5.3 利用proto生成 

protoc --go_out=plugins=grpc:./ .product.proto

值得注意的是,上面的生成命令中需要指定 grpc ,这样我们在文件中定义的 service 部分会生成对应的接口,我们只需要在服务端中实现这个接口即可。

5.4 服务端代码

接口实现:

启动方法代码 

import "google.golang.org/grpc"

func main()  {
	server := grpc.NewServer()
	service.RegisterProdServiceServer(server,service.ProductService)

	listener, err := net.Listen("tcp", ":8002")
	if err != nil {
		log.Fatal("服务监听端口失败", err)
	}
	_ = server.Serve(listener)
}

5.4 客户端代码

新建client目录,把上述生成的product.pb.go copy过来,因为生成的时候会把服务端和客户端一并生成。

func main()  {
	// 1. 新建连接,端口是服务端开放的8002端口
	// 没有证书会报错
	conn, err := grpc.Dial(":8002", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatal(err)
	}

	// 退出时关闭链接
	defer conn.Close()

	// 2. 调用Product.pb.go中的NewProdServiceClient方法
	productServiceClient := service.NewProdServiceClient(conn)

	// 3. 直接像调用本地方法一样调用GetProductStock方法
	resp, err := productServiceClient.GetProductStock(context.Background(), &service.ProductRequest{ProdId: 233})
	if err != nil {
		log.Fatal("调用gRPC方法错误: ", err)
	}

	fmt.Println("调用gRPC方法成功,ProdStock = ", resp.ProdStock)
}

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。