这是我参与「第五届青训营 」笔记创作活动的第 6 天
零、序言
字节内部使用的Kitex框架,性能不错,但出于能够参考学习的资料较少、仅支持unix内核,所以这边介绍另一种开源、高性能的RPC框架。
这就是由大名鼎鼎的Google负责的------gRPC。
他支持多种语言,多平台,并且也有着不俗的性能表现。
一、本课知识点
- gRPC介绍
- protobuf环境安装与配置
二、 详细知识点介绍
GRPC介绍
RPC协议介绍
RPC 全称为 Remote Procedure Call , 远程过程调用。这是一种协议,是用来屏蔽分布式计算中的各种调用细节,使你能够像调用本地方法一样,直接调用一个远程的函数。可以理解为一种规范。
下面简单说明一下客户端与服务端的沟通过程,以此来引出rpc的作用
客户端 与 服务器 沟通的过程:
- 客户端 发送 数据 (字节流)
- 服务器 接受并解析。根据约定知道需要执行上面。把结果返回给客户
RPC:
- 封装上述过程,使操作更加优化便捷
- 使用大家都认可的协议,使其规范化
- 做成一些框架,直接或间接产生利益
gRPC框架介绍
而gRPC是一种开源的,高性能的通用RPC框架,能够跨平台支持多种语言。(隔壁Kitex目前还只能支持unix平台)
在gRPC中,我们称调用方为client,被调用方为server。跟其他RPC框架一样,gRPC也是基于"服务定义"的思想。简单的来说,就是我们通过某种方式来描述一个服务,这种描述方式是语言无关的。在这个"服务定义"的过程种,我们描述了我们提供的服务名是什么,有哪些方法开源被调用,有什么样的入参,有什么样的回参
而就是说,在定义好了这些服务、方法之后,gRPC会频闭底层的细节,client只需要直接调用定义好的方法,就能够拿到预期返回的结果。 对于server端来说,只需要实现我们定义的方法。同样的,gRPC也会帮助我们屏蔽底层的细节,我们只需要实现所定义方法的具体逻辑即可。
你可以发现,在上面的描述过程种,所谓的"服务定义",就跟定义接口是类似的。我更愿意理解为是一种"约定",双方规定好接口,然后server实现接口,client调用接口,至于其他的细节就交给gRPC管理
此外,gRPC还是语言无关的,我们开源使用C++开发服务端,使用Golang、Java等作为客户端来调用服务器的接口。为了实现这一点,我们在"服务定义"和在编码解码过程中,同样应该做到语言无关。
ProtoBuf介绍
因此,gRPC使用了Protocol Buffss(谷歌开发的一套成熟的数据结构序列化机制)
我们可以把他当成一个代码生成工具以及序列化工具。这个工具可以把我们定义的方法,转换成特定语言的代码。比如你定义了一种类型的参数,他会帮你转换成Golang种的结构体,你定义的方法,体会帮你转换成func函数。此外,在发送请求和接受响应的时候,这个工具还会完成对应的编码和解码工作,将你即将发送的数据编码成gRPC能够传输的形式,又或者将即将接受到的数据解码成编程语言所能理解的数据格式。
可能有些同学对序列化和反序列化的概念不太理解,下面简单解释一下这两个概念。
- 序列化: 将数据结构或对象转换成二进制串的过程
- 反序列化: 将在序列化过程中产生的二进制串转换成数据结构或对象的过程
而protobuf是谷歌开源的一种数据格式,适合高性能,对想要速度有要求的数据传输场景。因为protobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。
相比于其他数据结构,他有着这样几点优势:
- 序列化后体积相比Json和XML很小,更适合网络传输
- 支持跨平台多语言
- 消息格式升级和兼容性好
- 序列化和反序列化速度很快
Proto
安装ProtoBuf
1、下载protocol buffers Releases · protocolbuffers/protobuf (github.com)
- Protocol buffers,通常称为 Protobuf,是Google开发的一种协议,可以对结构数据进行序列化和反序列化操作,在网络通信中很有用
- 我们下载对应操作系统的zip文件,解压,并将bin目录配置到环境变量中即可
- 最后在cmd或bash中输入
protoc命令查看是否安装并配置成功
2、安装gRPC核心库
go get google.golang.org/grpc
3、安装protocol编译器。它开源生成各种不同语言的代码。因此,除了这个编译器,我们还需要配合各个语言的代码生成工具。对于Golang来说,这个工具是protoc-gen-go。
这里有个小坑,github.com/golang/protobuf/protoc-gen-go和google.golang.org/protobuf/cmd/protoc-gen-go是不同的!前者是旧版本,后者是Google接管的新版本,他们的API是不同的,用于生成的命令,生成的文件都是不一样的。由于目前的gRPC-go源码中的example是使用后者的生成方式,所以我们也采用google版本。
下面我们通过命令安装两个库(因为这些文件在安装grpc时以及下载了,这里只需要install即可)
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Proto文件编写
下面简单写一个小demo,新建两个文件夹,分别作为客户端和服务端。
proto文件内容如下(可以当作模板记下来)
// 使用proto3语法
syntax = "proto3";
// 生成的go文件处于哪个目录哪个包中
// 这里声称在当前目录,service包中
option go_package = ".;service";
// 我们需要定义一个服务,在服务中需要有一个方法,这个方法可以接收客户端参数,返回服务端响应
// 其实很容易可以看出,我们定义了一个service,称为SayHello,这个服务有一个rpc方法,名为SayHello
// 这个方法会发送一个HelloRequest返回一个HelloResponse
service SayHello {
rpc SayHello(HelloRequest) returns (HelloResponse) {}
}
// message关键字,可以理解为结构体
// 这个比较特别的是变量后的"赋值"(这里并不是赋值,而是定义这个变量在message中的位置)
message HelloRequest {
string requestName = 1;
// int64 age = 2;
}
message HelloResponse {
string responseMsg = 1;
}
接下来可以通过protoc生成对应语言的代码,打开Terminal,进入proto目录,输入一些代码即可
两个命令(当作模板可以记下)
protoc --go_out=. hello.proto
protoc --go-grpc_out=. hello.proto
输入完可以发现在proto目录下生成了两个文件,我们使用时只需要重写或修改其中的我们定义的方法,加上业务逻辑即可
三、实践练习例子
实践的部分代码也已经贴在上面了,以及这里是GitHub
四、课后个人总结
其实我对于gRPC的学习已经基本快速入门了!(笔记只上传一点才不是要水笔记呢!)
这几天没课的时候,将会连载gRPC以及有关网络相关的文章~
除了字节官方推荐的Kitex,gRPC或许能成为你的选择~