知识卡片

序列化格式的容错性:纯二进制对结构变化极脆弱

普通读书笔记卡

内容

数据传输对象要在网络上传输,就必须把自己序列化成某种格式——选哪种格式取决于连接两端是什么、连接上能跑什么、以及序列化实现的难易程度;大多数平台自带简单对象的序列化能力(Java的二进制序列化、.NET的二进制/XML序列化),这些内建机制通常已经够用,因为DTO本身结构简单,用不上处理领域模型那种复杂对象关系的能力。但一个容易被忽视的问题是:DTO的定义总有一天会变,而服务端和客户端未必总能同步更新——理论上应该同步,实际中经常做不到。这时候序列化格式的选择就决定了系统对这种”版本错位”的容忍度:纯二进制序列化对结构变化极度脆弱,任何结构上的改动都会导致反序列化错误甚至失败——哪怕只是新增了一个无关紧要的可选字段,一样会出问题,长期看纯二进制序列化会带来大量麻烦、让通信变得非常脆弱。相比之下,XML序列化对这类变化的适应力强得多;另一种可行方案是用带一定容错能力的二进制格式(比如用字典结构来做二进制序列化)——作者虽然并不喜欢把字典直接当DTO本体用(会丢失强类型接口带来的清晰性),但承认这种”字典式”序列化在应对版本不同步时确实提供了更好的弹性和容错性。可迁移启发:给跨进程/跨服务的通信选序列化协议时,除了看现在的性能和易用性,还要认真评估”服务端和客户端版本无法保证同时升级”这个几乎必然会发生的场景——协议对结构演进的容忍度,往往比协议本身的传输效率更能决定系统长期运行的稳定性。

参考来源

- 位置:《企业应用架构模式》第二部分"模式"之"第15章 分布模式"之"15.2.1 运行机制"(源文件:_epub-src/OEBPS/Text/000185.html) - 结论依据:原文说明"用一个过时客户来访问一个服务器时总会带来一定的问题,但是序列化机制会或多或少使问题更麻烦。使用纯粹的二进制序列化将会使数据传输对象的通信完全丢失,因为此时任何结构上的变化都会导致反序列化的错误和失败。即使一个无关紧要的变化,例如增加一个选择域,都会产生这样的问题……其中之一就是XML序列化,它可以使得对象对于变化更具有弹性……字典……为同步机制带来了许多容错性和弹性",直接支撑本卡结论。 - 原始内容:最终,直接使用二进制序列化将会引入大量的问题,并且使得通信变得非常脆弱。