grpc序列化方式是什么?他的原理是怎么样的?
1 个回答
用眼睛是看不到事物的本质的,只有心灵才能够洞察一切。铁血无双#### **1. gRPC 采用的序列化方式** gRPC 默认使用 **Protocol Buffers(protobuf)** 作为序列化方式,主要特点如下: - **二进制格式**,相比 JSON 和 XML 更紧凑,体积小,解析快。 - **跨语言支持**,适用于多种编程语言,如 Java、Go、Python、C++ 等。 - **前向/后向兼容性**,支持在不破坏已有结构的情况下添加新字段,使得 API 升级更加灵活。 - **基于 HTTP/2 传输**,利用多路复用和头部压缩提升通信效率。 #### **2. gRPC 的序列化和反序列化流程** 在 gRPC 通信过程中,数据的处理方式如下: 1. 客户端调用 gRPC 方法,传入一个 protobuf 定义的消息对象。 2. protobuf 进行序列化,将数据转换为二进制格式(Tag-Length-Value 结构)。 3. gRPC 通过 HTTP/2 发送二进制数据到服务器。 4. 服务器接收数据并反序列化,解析为 protobuf 对象。 5. 服务器处理请求并生成响应,再经过 protobuf 序列化为二进制格式。 6. 服务器返回数据给客户端,客户端反序列化解析数据并处理。 #### **3. gRPC 采用 Protobuf 序列化的核心原理** gRPC 之所以选择 Protobuf 作为序列化方式,主要是因为 Protobuf 采用了一套高效的 **二进制编码机制**,主要原理如下: ##### **(1)Tag-Length-Value(TLV)结构** Protobuf 使用 **TLV 结构**(Tag-Length-Value),避免了 JSON 这种文本格式中存储字段名的额外开销。 - **Tag**(字段标识符):使用 **变长整数(Varint)** 编码,包含字段号和类型信息。 - **Length**(可选):变长数据的字节长度(仅适用于 `string`、`bytes` 这些变长类型)。 - **Value**(值):字段的实际数据,存储为紧凑的二进制格式。 ##### **(2)变长整数(Varint)编码** Protobuf 采用 **Varint 编码**,即 **小数值占用更少字节**,减少存储空间。 - Varint **基于 7-bit 存储**,如果数值 < 128 仅用 1 字节存储,大数值会自动扩展。 例如: - `150`(十进制)= `10010110`(二进制) - Varint 编码后: ```hex 96 01 ``` - `96` = `1001 0110`(最高位 `1` 表示后续还有字节) - `01` = `0000 0001`(最高位 `0` 表示结束) - 比起 JSON 直接存储 `150`(占 4 字节),Varint 编码可**节省 50%+ 存储空间**。 ##### **(3)ZigZag 编码(优化负数存储)** 负整数在二进制补码存储时很大,使用 Varint 存储会占用大量空间。 Protobuf 使用 **ZigZag 编码**,把负数映射为小整数,提高压缩率: - `-1` → `1` - `-2` → `3` - `-3` → `5` - 这样 `-1` 仅需 **1 字节** 存储,节省空间。 ##### **(4)省略默认值** Protobuf **不会存储默认值**,如: - `int32` 默认为 `0` - `bool` 默认为 `false` - `string` 默认为 `""` 例如,字段 `age=0` 在 JSON 中仍需 `"age": 0`,但在 Protobuf 中完全**不会存储**,减少冗余数据。 ##### **(5)二进制存储 vs. 文本存储** JSON 是文本格式,需要存储 **字段名、分隔符、引号**,额外占用空间。 Protobuf 直接使用 **二进制存储**,避免冗余信息,**体积缩小 50%~80%**,解析速度快 10 倍以上。 #### **4. Protobuf vs JSON 存储大小对比** **示例数据** ```json {"id":150, "name":"Tom", "age":25, "gender":"male"} ``` - **JSON 大小** ≈ **50+ 字节** - **Protobuf 序列化后** ≈ **10-15 字节** - **节省 70%+ 空间**,同时解析速度提升 10 倍以上。 #### **5. 其他序列化方式** 尽管 gRPC 默认使用 **Protobuf**,但它**并不强制**使用,可以扩展支持: - **JSON**(gRPC-Web 或 gRPC-JSON 转换) - **FlatBuffers**(零拷贝解析,适用于低延迟场景) - **MessagePack / CBOR**(其他二进制序列化格式) 但通常 **Protobuf 是 gRPC 的最佳选择**,因为它在体积和解析速度方面表现最佳。 #### **6. 总结** | 机制 | 作用 | 优势 | |------|------|------| | **TLV 结构** | 避免存储字段名,减少冗余 | 数据更紧凑 | | **Varint 编码** | 小数用更少字节存储 | 节省 50%+ | | **ZigZag 编码** | 负数优化,减少额外字节 | 提高负数压缩率 | | **省略默认值** | 避免存储 `0`、`false`、`""` | 减少不必要字段 | | **二进制存储** | 无需引号/分隔符 | 体积缩小 50%~80% | **为什么 gRPC 选择 Protobuf 作为序列化方式?** 1. 数据体积小(比 JSON 省 50%~80%) 2. 序列化和反序列化速度快(比 JSON 快 10 倍) 3. 网络传输效率高(配合 HTTP/2,减少开销) 4. 跨语言支持,前向/后向兼容性强 5. 省略默认值,避免存储无用数据 因此,gRPC 选择 **Protobuf** 作为默认序列化方式,确保高效、紧凑、快速的远程通信。发布于 2025-02-09 16:04 •IP属地 安徽举报评论收藏
公众号进入网站体验更佳

