gRPC 是一个高性能、开源、通用的RPC框架,由Google推出,基于HTTP/2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库。
gRPC 提供 protocol buffer 编译插件,能够从一个服务定义的 .proto 文件生成客户端和服务端代码。通常 gRPC 用户可以在服务端实现这些API,并从客户端调用它们。
gRPC 允许你定义四类服务方法:
Google Protocol Buffer( 简称 Protobuf) ,Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
Protobuf实际是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。
相比较而言,Protobuf有如下优点:
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
Tag块并不是只表示数据类型,其中数据编号也在Tag块中,Tag的生成规则如下:Tag块的后3位表示数据类型,其他位表示数据编号。Tag中1-15编号只占用1个字节,所以确保编号中1-15为常用的,减少数据大小。
其中Length不一定有,依据Tag确定,例如数值类型的数据,使用VarInts不需要长度,就只有Tag-Value,string类型的数据就必须是Tag-Length-Value
类型 | 释义 | 备注 |
---|---|---|
0 | 可变长度编码 | int32 int64 uint32 uint64 sint32 sint64 bool enum |
1 | 64位固定长度 | fixed64 sfixed64 double |
2 | value 的长度 | string bytes message packed repeated fiels |
3 | Start Group | 已废弃 |
4 | End Group | 已废弃 |
5 | 32位长度 | fixed32 sfixed32 float |
(field_number << 3) | wire_type
低三位表示wire type,其他的位表示field number(编号)。
int值一般都是固定的4字节,可表示的整数范围为-2^31——2^31-1,但是实际开发中用到的数字均比较小,会造成字节浪费。
Varints是protobuf的序列化整型数据的一种编码方式,它的优点是整型数据的值越小,编码后所用的字节数越小。
经过Varints编码后的数据,它的每一个字节8bit的高位代表一个标记位。
先看最简单的数值1,一个字节足以表示它,所以它的标记位置0:
0000 0001
再看数值300,经过Varints编码后的序列:
1010 1100 0000 0010
换算的时候,从左到右,依次将每个字节的高位(标志位)去掉,Protocol Buffer是低位在前,转换后拼接
1010 1100 0000 0010
(去除标志位)
→ 010 1100 000 0010
(转换拼接)
→ 000 0010 010 1100
(进制)
→ 300
可变长度编码唯一的缺点就是当数很大的时候int32需要占用5个字节,但是从统计学角度来说,一般不会有这么大的数。
对于负数的处理方式是不同的。如果用int32或者int64来编码一个负数的话,通常需要耗费10个字节来表示,因为负数在计算机中是以补码表示的,相当于一个数值很大的无符号数。
所以这个时候就需要用「有符号」的整型(sint32,sint64)来表示负数了,它们先使用ZigZag编码方式将负数转换为绝对值较小正数,再进行Varints编码。
message Test1{
required int32 id = 1;
}
如果我们将number赋值为300,则Message进行编码序列化以后以16进制输出为
08 96 01
其中第一个字节08
0000 1000
wire type为0,field name为1。符合id的类型是int32,编码方式是Varints,field是1的这一情况。
12c 02则分别为1010 1100和0000 0010的16进制
message Test2
{
required string str = 2;
}
如果将str赋值为’testing’,然后把经过protobuf编码序列化后的数据以16进制的方式输出
12 07 74 65 73 74 69 6e 67
第一个字节0x12表示field name为2,wire type为2。第二个字节0x07表示数据长度为7,所以后面7个字节就是使用UTF8编码的testing。