1.protobuf如何提升编码格式
本篇知识点来自:https://time.geekbang.org/column/article/247544
protobuf是一种针对多种语言的编解码工具。它的编码速度很快,并且编码后的字符流体积远远小于json等格式,能节约大量带宽。grpc的底层编解码协议就是protobuf。
原理:它是通过把消息里的ASCII字段名省略,用proto中定义的数字代替。这样在编解码时就可以大量降低带宽。protobuf消息序列是按照字段序号、值类型、字段值的顺序来编码的。
如下例子proto文件:
message Person{
string name=1;
uint32 id = 2;
enum SexType{
MALE = 0;
FEMALE = 1;
}
SexType sex = 3;
}
对于消息体为:{"name":"John", "id":1234, "sex":"FEMALE"},我们可以尝试把它编码成二进制流。
在编码前需要知道:
A. 字段序号与值类型可以组成多个整字节;且多个字节时也是在高位字节的第一个字节末3bit位留给值类型。具体如下:
字段序号<=16,1个字节,5bit字段序号+3bit字段类型
字段序号<=2027,2个字节,5bit字段序号+3bit字段类型+1字节字段值
······
B.值类型3bit
其中类型2时需要在值类型后面,字段值前面加上字段值长度。128(2的7次方)字节以内,可以用1个字节表示,16384(2的14次方)时需要两个字节以此类推。
C.字段值
如果有大量字符串,可以使用 Huffman 等算法压缩。
如果字段值是类型默认值,将会被跳过。
枚举类型,则字段值可以用枚举值中的数字代替。
消息二进制流:
"name":"John": name字段名00001, 值类型010,字符串所以还有长度4即00000100, john的ascii流比较长,这里就不在列出来;
"id":1234 : id字段名00010,值类型000,1234转成二进制即11010010 00001001;
"sex":"FEMALE": id字段名00011,值类型000,FEMALE即是1转成二进制即00000001;
这些连着串起来就是消息的二进制流了。
2.grpc
本节知识点来自: https://time.geekbang.org/column/article/247812
gRPC是目前市面上性能最好的RPC框架之一, 支持 QUIC、HTTP/1 等多种协议,但鉴于 HTTP/2 协议性能好,应用场景又广泛,因此 HTTP/2 是 gRPC 的默认传输协议。
gRPC 可以简单地分为三层,包括底层的数据传输层,中间的框架层(框架层又包括 C 语言实现的核心功能,以及上层的编程语言框架)),以及最上层由框架层自动生成的 Stub 和 Service 类。
http/2的DATA帧存放着上面的消息二进制流,并不是直接就是protobuf消息二进制流,在流前面还会有5个字节。第一个字节表示是否压缩过,后面字节表示消息的长度。http/2中的每个stream就对应着1次rpc请求。
grpc有四种请求方式,一元模式即服务器与客户端一应一答时,每个stream里就一个DATA帧,当变成流式的时,每个stream里就可以有多个DATA帧。通过消息长度来区分边界。