protobuf+RPC
简介
protobuf是是一种google定义的结构化数据格式,与json,XML功能相似的一种结构化数据格式,
用于在网络通讯间的数据序列化和反序列化,以用于网络传输。
特点
解析速度快;
占用空间小;
兼容性好;
很适合做数据存储或网络通讯间的数据传输。
原理
序列化 & 反序列化简单 & 速度快的原因是:
a. 编码 / 解码 方式简单(只需要简单的数学运算 = 位移等等,Varint、Zigzag编码)
b. 采用protobuf自身的框架代码和编译器共同完成
即序列化后的数据量体积小的原因是:
a. 采用了独特的编码方式,如Varint、Zigzag编码方式等等
b. 采用T - L - V 的数据存储方式:减少了分隔符的使用 & 数据存储得紧凑
Varint
中每个 字节 的最高位 都有特殊含义:
- 如果是 1,表示后续的 字节 也是该数字的一部分
- 如果是 0,表示这是最后一个字节,且剩余 7位 都用来表示数字
为了更好地减少 表示负数时 的字节数,protobuf在varint编码上又增加了zigzag编码方式进行编码(移位操作)
T-L-V数据存储方式:
T - L - V
存储方式的优点是
- 不需要分隔符 就能 分隔开字段,减少了 分隔符 的使用
- 各字段 存储得非常紧凑,存储空间利用率非常高
- 若 字段没有被设置字段值,那么该字段在序列化时的数据中是完全不存在的,即不需要编码
在使用varint编码后,只需要用T-V来表示,大大节省了空间。
总结
protobuf使用varint编码和T-V表示方式,大大节省序列化后的数据空间,并且编码方式简单,序列化速度很快,并且protobuf直接对数据进行处理,与语言平台无关,可以供任意语言使用。
RPC
RPC远程过程调用,是一种封装了各层网络协议,并包含序列化和反序列化功能的一种通讯框架,基于protobuf的gRPC相当于序列化和反序列化功能是用protobuf实现的。
参考链接:https://blog.csdn.net/b1303110335/article/details/79557292
- Client A的应用层代码中,调用了Calculator的一个实现类的add方法,希望执行一个加法运算;
- 这个Calculator实现类,内部并不是直接实现计算器的加减乘除逻辑,而是通过远程调用Service B的RPC接口,来获取运算结果,因此称之为Stub;
- Stub怎么和Service B建立远程通讯呢?这时候就要用到远程通讯工具了,也就是图中的Run-time Library,这个工具将帮你实现远程通讯的功能,比如Java的Socket,就是这样一个库,当然,你也可以用基于Http协议的HttpClient,或者其他通讯工具类,都可以,RPC并没有规定说你要用何种协议进行通讯;
- Stub通过调用通讯工具提供的方法,和Service B建立起了通讯,然后将请求数据发给Service B。需要注意的是,由于底层的网络通讯是基于二进制格式的,因此这里Stub传给通讯工具类的数据也必须是二进制,比如calculator.add(1,2),你必须把参数值1和2放到一个Request对象里头(这个Request对象当然不只这些信息,还包括要调用哪个服务的哪个RPC接口等其他信息),然后序列化为二进制,再传给通讯工具类,这一点也将在下面的代码实现中体现;
- 二进制的数据传到Service B这一边了,Service B当然也有自己的通讯工具,通过这个通讯工具接收二进制的请求;
- 既然数据是二进制的,那么自然要进行反序列化了,将二进制的数据反序列化为请求对象,然后将这个请求对象交给Service B的Stub处理;
- 和之前的Service A的Stub一样,这里的Stub也同样是个“假玩意”,它所负责的,只是去解析请求对象,知道调用方要调的是哪个RPC接口,传进来的参数又是什么,然后再把这些参数传给对应的RPC接口,也就是Calculator的实际实现类去执行。很明显,如果是Java,那这里肯定用到了反射。
- RPC接口执行完毕,返回执行结果,现在轮到Service B要把数据发给Service A了,怎么发?一样的道理,一样的流程,只是现在Service B变成了Client,Service A变成了Server而已:Service B反序列化执行结果->传输给Service A->Service A反序列化执行结果 -> 将结果返回给Application,完毕。
总结:RPC包含了网络传输,序列化和反序列化,call id映射等。