3. 序列化基础概念:序列化与反序列化的定义、作用、在BFF中的位置、常见序列化格式对比
3.1 序列化与反序列化的定义
序列化(Serialization) 是将内存中的对象、数据结构或状态信息,转换为可存储或可传输的字节序列(如 JSON 字符串、二进制流)的过程。反序列化(Deserialization) 则是其逆过程,将字节序列还原为内存中的对象。
核心公式:
序列化:对象 → 字节序列(传输/存储格式)
反序列化:字节序列 → 对象(内存可操作格式)
序列化:对象 → 字节序列(传输/存储格式)
反序列化:字节序列 → 对象(内存可操作格式)
3.2 序列化的作用
- 网络传输:将复杂对象扁平化为字节流,便于在 HTTP、gRPC、消息队列等协议中传输。
- 持久化存储:将对象状态保存到文件、数据库或缓存(如 Redis)中。
- 跨语言/跨平台通信:不同语言(Java、Go、Python)通过统一序列化格式交换数据。
- 深拷贝:通过序列化/反序列化实现对象的完整复制。
3.3 序列化在 BFF 中的位置
在 BFF(Backend For Frontend)聚合服务中,序列化发生在两个关键边界:
- 上游边界:BFF 从下游微服务获取数据时,需要反序列化微服务返回的响应(如 Protobuf 二进制流)。
- 下游边界:BFF 将聚合后的数据序列化后,通过 HTTP Response 返回给前端客户端(通常为 JSON)。
BFF 序列化策略要点:上游(微服务→BFF)通常使用二进制序列化(Protobuf/Thrift)以提升性能;下游(BFF→前端)通常使用 JSON 以保证浏览器兼容性和调试便利性。这种“双模序列化”是 BFF 架构的常见模式。
3.4 常见序列化格式对比
下表从多个维度对比四种主流序列化格式:
| 维度 | JSON | XML | Protobuf | Thrift |
|---|---|---|---|---|
| 数据格式 | 文本(UTF-8) | 文本(UTF-8) | 二进制 | 二进制 |
| 可读性 | 高 | 中 | 低(需工具解码) | 低(需工具解码) |
| 序列化速度 | 中 | 慢 | 快 | 快 |
| 数据体积 | 较大(冗余字段名) | 很大(标签冗余) | 小(字段编号代替名称) | 小(字段编号代替名称) |
| Schema 要求 | 无(动态类型) | 可选(DTD/XSD) | 必须(.proto 文件) | 必须(.thrift 文件) |
| 跨语言支持 | 广泛(原生支持) | 广泛 | 良好(官方多语言) | 良好(官方多语言) |
| 向后兼容 | 手动处理 | 手动处理 | 内置(字段编号/可选) | 内置(字段编号/可选) |
| 典型应用场景 | Web API、浏览器 | 遗留系统、配置文件 | 微服务间 RPC、高性能场景 | 跨语言服务、数据管道 |
3.5 序列化格式选择决策树
在 BFF 架构中,选择序列化格式可参考以下决策逻辑:
- 如果数据需要被浏览器直接消费 → 选择 JSON(前端原生支持,无需额外解析库)。
- 如果 BFF 与微服务之间需要高性能通信 → 选择 Protobuf(体积小、速度快、兼容性好)。
- 如果团队已有 Thrift 基础设施 → 选择 Thrift(与现有 RPC 框架集成度高)。
- 如果对接遗留系统或需要严格文档化 → 选择 XML(但 BFF 场景中已较少使用)。
3.6 序列化性能关键指标
在 BFF 场景中,评估序列化格式时需关注以下指标:
| 指标 | 说明 | BFF 影响 |
|---|---|---|
| 序列化吞吐量 | 每秒可序列化的对象数量 | 直接影响 BFF 请求处理能力(QPS) |
| 序列化后体积 | 字节序列的大小 | 影响网络传输延迟和带宽消耗 |
| CPU 开销 | 序列化/反序列化消耗的 CPU 时间 | 影响 BFF 实例的 CPU 利用率 |
| 内存分配 | 序列化过程中产生的临时对象 | 影响 GC 压力和内存占用 |
常见误区:不要仅根据“体积小”就选择二进制格式。如果 BFF 的主要瓶颈是 CPU 而非网络带宽,JSON 的简单解析可能反而更优。务必基于实际压测数据做决策。
3.7 代码示例:JSON vs Protobuf 序列化对比
以下示例展示相同数据结构在 JSON 和 Protobuf 下的序列化结果差异:
// 原始数据对象(用户信息)
{
"userId": 1001,
"userName": "Alice",
"email": "alice@example.com",
"age": 28,
"tags": ["vip", "premium"]
}
// JSON 序列化结果(文本,共 112 字节)
{"userId":1001,"userName":"Alice","email":"alice@example.com","age":28,"tags":["vip","premium"]}
// Protobuf 序列化结果(二进制,共 38 字节)
// 使用字段编号代替字段名,体积减少约 66%
// 0x08 0xE9 0x07 0x12 0x05 0x41 0x6C 0x69 0x63 0x65 ...
关键结论:Protobuf 通过字段编号(field number)和紧凑的 Varint 编码,在数据体积上具有显著优势。对于 BFF 中高频调用的微服务接口,使用 Protobuf 可减少 50%~70% 的传输数据量。