3. 序列化基础概念:序列化与反序列化的定义、作用、在BFF中的位置、常见序列化格式对比

3.1 序列化与反序列化的定义

序列化(Serialization) 是将内存中的对象、数据结构或状态信息,转换为可存储或可传输的字节序列(如 JSON 字符串、二进制流)的过程。反序列化(Deserialization) 则是其逆过程,将字节序列还原为内存中的对象。

核心公式:
序列化:对象 → 字节序列(传输/存储格式)
反序列化:字节序列 → 对象(内存可操作格式)

3.2 序列化的作用

  • 网络传输:将复杂对象扁平化为字节流,便于在 HTTP、gRPC、消息队列等协议中传输。
  • 持久化存储:将对象状态保存到文件、数据库或缓存(如 Redis)中。
  • 跨语言/跨平台通信:不同语言(Java、Go、Python)通过统一序列化格式交换数据。
  • 深拷贝:通过序列化/反序列化实现对象的完整复制。

3.3 序列化在 BFF 中的位置

在 BFF(Backend For Frontend)聚合服务中,序列化发生在两个关键边界:

  1. 上游边界:BFF 从下游微服务获取数据时,需要反序列化微服务返回的响应(如 Protobuf 二进制流)。
  2. 下游边界:BFF 将聚合后的数据序列化后,通过 HTTP Response 返回给前端客户端(通常为 JSON)。
BFF 序列化位置架构图 BFF 序列化/反序列化边界 前端客户端 BFF 聚合服务 微服务 A 微服务 B 请求(JSON) 响应(JSON) Protobuf Protobuf 序列化(对象→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 场景中已较少使用)。
BFF 序列化格式选择决策树 BFF 序列化格式选择决策树 BFF 序列化需求 前端直接消费? 微服务间通信? JSON Protobuf Thrift XML 是 是 提示:BFF 通常采用“上游 Protobuf + 下游 JSON”的双模策略

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% 的传输数据量。