Grpc+protocol buffer使用学习

An introduction to gRPC and protocol buffers.

GRPC和协议缓冲区:

gRPC可以使用协议缓冲区作为它的接口定义语言(IDL)和它的底层消息交换格式。
个人理解:一种交互协议,主要实现数据的传输,体积小,更加便捷,高效,由google公司开发的proto协议缓冲区,支持多种语言开发和生成。

一, GRPC概述
在gRPC中,客户机应用程序可以直接调用另一台机器上的服务器应用程序上的方法,就好像它是本地对象一样,这使您更容易创建分布式应用程序和服务。
正如在许多RPC系统中一样(如springcloud自带的rpc交互),gRPC基于定义服务的思想,指定可以通过其参数和返回类型远程调用的方法。

在服务器端,服务器实现此接口并运行gRPC服务器来处理客户机调用。
在客户端,客户端有一个存根(在某些语言中仅称为客户端),它提供相同的方法。

gRPC客户端和服务器可以在各种环境中运行并相互通信——从谷歌中的服务器到您自己的桌面——并且可以用gRPC支持的任何语言编写。因此,例如,您可以轻松地用Java创建gRPC服务器,用Go、Python或Ruby创建客户机。此外,最新的谷歌api将拥有其接口的gRPC版本,使您可以轻松地在应用程序中构建谷歌功能。

二, GRPC效果实现
默认情况下,gRPC使用协议缓冲区,这是谷歌用于序列化结构化数据的成熟开源机制(尽管它也可以用于JSON等其他数据格式)。下面是它如何工作的一个快速介绍。如果您已经熟悉协议缓冲区,可以忽略。

使用协议缓冲区的第一步是定义要在原型文件中序列化的数据的结构:
用一个扩展名为.proto的普通文本文件。(一般的请求协议需要接口,请求体,该处使用文件)
协议缓冲区数据结构为消息,其中每个消息都是一个小的信息逻辑记录,其中包含一系列名为字段的名-值对。这里有一个简单的例子:

message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}

然后,一旦指定了数据结构,就可以使用协议缓冲区编译器protoc从原始定义中以首选语言生成数据访问类。它们为每个字段提供了简单的访问器,如name()和set_name(),以及将整个结构序列化/解析为原始字节的方法。因此,例如,如果您选择的语言是c++,在上述示例上运行编译器将生成一个名为Person的类。然后可以在应用程序中使用这个类来填充、序列化和检索Person协议缓冲区消息。
您在普通的proto文件中定义gRPC服务,RPC方法参数和返回类型指定为协议缓冲区消息:

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
gRPC使用带有特殊gRPC插件的protoc从你的原型文件中生成代码:                     你会得到生成的gRPC客户端和服务器代码,以及用于填充、序列化和检索你的消息类型的常规协议缓冲区代码。

三, 缓冲协议(protocol buffer )
理解:协议缓冲区是一种语言无关、平台无关的可扩展机制,用于序列化结构化数据。
协议缓冲区是谷歌用于序列化结构化数据的语言无关、平台无关、可扩展的机制——想想XML吧,但更小、更快、更简单。一旦定义了数据的结构化方式,就可以使用特殊生成的源代码轻松地从各种数据流和使用各种语言编写和读取结构化数据。
该处解释上述grpcs使用的prot文档:该文档是用来定义缓冲协议的,内部大致需要定义的

syntax = "proto3";(版本)
option java_multiple_files = true;()
package  ***;(包名)
service方法名{rpc 方法名2(enity即message)returns(enity)}
message ***{String **}

四, Proto(二进制)使用安装步骤
下载protocol buffer compiler.编译器(处理prot文档和生成所需要语言的协议)
目前proto版本推荐proto3, 您可以使用以下命令在Linux或macOS下使用包管理器安装协议编译器protoc。(安装前请检查版本)

Linux:
$ apt install -y protobuf-compiler
$ protoc --version  # Ensure compiler version is 3+

MAX:
$ brew install protobuf
$ protoc --version  # Ensure compiler version is 3+
 	从预编译的二进制文件安装最新版本的协议编译器:
  1. 从github.com/google/protobuf/release与你的操作系统和计算机架构相对应的zip文件(protoc--.zip),或者使用以下命令获取文件:
$ PB_REL="https://github.com/protocolbuffers/protobuf/releases"
$ curl -LO $PB_REL/download/v3.13.0/protoc-3.13.0-linux-x86_64.zip
  1. 将文件解压缩到$HOME/下。本地或您选择的目录:
$ unzip protoc-3.13.0-linux-x86_64.zip -d $HOME/.local
  1. 更新环境的path变量,以包含可执行原文件的路径:
$ export PATH="$PATH:$HOME/.local/bin"

五, Proto安装补充(四)操作
*此处以go语言为演示,此协议方式支持C#,C++,Dart,Go,JAVA,Node,Ruby等多种语言,具体操作可见官方

https://grpc.io/docs/languages/go/quickstart/ *

怎样在Go中使用Grpc:
1,前提准备:
① 安装Go(可查询官网https://golang.org/doc/install)
② 安装相应编译器protoc
(该处可总结四种方式来安装此编译器,前两种为windows系统,第三种适用Linux,第四种为MacOs系统)
2.1 可直接通过git官网获取相应版本的protoc文件,并修改相应的环境变量即可
推荐链接:https://github.com/protocolbuffers/protobuf/releases/tag/v3.14.0
(protoc --version查看已安装版本)

	2.2 通过包管理器chotolate安装编译器protoc
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
然后通过命令choco install protoc安装protoc编译器

2.3 Linux下install编译器(apt或apt-get ——Debian或Ubuntu系统包管理器,可到官网下载)

$ apt install -y protobuf-compiler
$ protoc --version # Ensure compiler version is 3+

2.4 MacOs(使用自带的Homebrew,可致官网下载

(https://brew.sh/))
		$ brew install protobuf
		$ protoc --version  # Ensure compiler version is 3+

③ Go协议编译器插件(该处的export属于Linux命令,windows可用$env或其他shell命令,本文推荐Linux)
3.1 安装go编译插件

$ export GO111MODULE=on  # Enable module mode
$ go get google.golang.org/protobuf/cmd/protoc-gen-go \
            google.golang.org/grpc/cmd/protoc-gen-go-grpc

3.2 更新你的路径,以便protoc编译器可以找到插件

  $ export PATH="$PATH:$(go env GOPATH)/bin"

*注:此步骤主要为了安装编译protoc-gen-go插件,第六步可自动配置(有些许差异未知版本不可控,也可自行在git上下载插件https://github.com/golang/protobuf/releases

六, Grpc编译打印helloword测试
1, 下载测试源码:

$ git clone -b v1.34.0 https://github.com/grpc/grpc-go

2, 进入目录:

$ cd grpc-go/examples/helloworld

3, 同目录下编译执行服务代码:(此处会下载步骤五所需要的一些插件)

$ go run greeter_server/main.go

4, 从另一个终端,编译并执行客户端代码,查看客户端输出:

$ go run greeter_client/main.go
Greeting: Hello world

至此,恭喜你!您刚刚使用gRPC运行了一个客户机-服务器应用程序。

七, 修改原有proto文件及go方法
1, 尝试修改原有目录下的proto定义文件(本文在helloworld/helloworld.proto目录文件上进行修改)
该处的proto即为定义文件,可通过修改定义改变其属性变化和方法
(推荐学习定义链接https://grpc.io/docs/languages/go/basics/
你所需要知道的是服务器和客户端存根都有一个SayHello() RPC方法,它从客户端接受一个HelloRequest参数并从服务器返回一个HelloReply,这个方法是这样定义的:

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

尝试在其中添加一个SayHelloAgain()方法,使用相同请求和响应,修改后如下:

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
		*记得保存文件!!!

2,重新生成grpc代码
(在使用新的服务方法之前,需要重新编译更新后的.proto文件。)
在之前helloword目录下执行如下代码(该处”\”为Bash换行风格,其他)

$ protoc --go_out=. --go_opt=paths=source_relative \
	--go-grpc_out=. --go-grpc_opt=paths=source_relative \
 helloworld/helloworld.proto

这将重新生成helloworld/helloworld.pb和helloworld / helloworld_grpc.pb。go文件,其中包含:
填充、序列化和检索HelloRequest和HelloReply消息类型的代码;
生成的客户端和服务器代码;
*这部分极有可能因为上诉的go插件原因而更新失败,导致再编译无法通过,所以检查go插件配置(我测试这步时windows会有一定问题)

3,更新main.go文件
您已经重新生成了服务器和客户端代码,但仍然需要在示例应用程序的人工编写部分中实现和调用新方法。代码如下:
2.1 打开greeter_server /main.go, 添加以下function代码:

func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}

2.2 打开greeter_client/main.go,添加一下function代码:

	     r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
        log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())

5, 运行
1, 运行服务端main.go方法

go run greeter_server/main.go

2, 运行客户端并传递参数

go run greeter_client/main.go Alice

得到结果:

Greeting: Hello Alice
Greeting: Hello again Alice

恭喜你,成功完成GRPC简单测试。
以上便个人总结的一些关于Grpc及protocol buffer的一些使用经验,鉴于各系统使用命令不一,上诉推荐用Linux系统,windows测试时,go插件会有些许问题,但安装合适版本即可。Macs系统暂未测试,有大佬愿意的可以尝试一下。上诉测试代码来自与git,里面东西可以根据实际需求改变,以及proto文件本文只做参考。

感谢各位大佬的指教和帮助,如有不妥之处,还望多多指教。(●’◡’●)

猜你喜欢

转载自blog.csdn.net/MatChen/article/details/111225977