Google不久前开源了一种数据交换格式——Protocol Buffers。在它语焉不详的名字背后,藏着的是:
message Person {要明确指定字段名称对应的序号(称为“tag”),才能在以后变更格式。如果用自动分配的序号,对格式的更改会引起麻烦(比如在中间插入一个新字段)。为什么呢?因为在二进制格式,tag是用来说明某段字节编码所表示的(协议描述里的)字段的。明确地分配tag序号,搭配上忽略未知tag的规则,在变更格式的时候就可以从容增加字段而不影响已有字段。
required int32 id = 1;
required string name = 2;
optional string email = 3;
}
总而言之,如果你想要松散耦合的终端程序,保留最大的灵活性,那就接着用XML,包装进SOAP封包或者符合底层传输(也就是说HTTP,因为依赖其他传输形式的REST还没有真正被定义)要求的RESTful封包。 如果你需要二进制格式,Protocol Buffers是其中一个答案……但ICE也是,甚至CORBA(虽然参与者日少已经使它失去了吸引力)。不要仅仅由于贴上了Google的商标,就忽略了对技术优势和劣势的分析。
与XML或JSON的比较很容易使人忽略Protocol Buffers其实是对现有技术的重新实现。除了前面已经提到的,还有一项广泛使用的技术——ASN.1也是其竞争对手。ASN.1虽然已经存在了几十年,却不怎么显山露水。从用ASN.1描述的格式名单来看,这是非常奇怪的一件事情,请看看其中的几种格式:
ASN.1的用途广泛;例如,日常的电信通信就用到ASN.1编码的数据。ASN.1基于与Protocol Buffers相似的概念——它也用IDL描述数据,用编译器为目标语言生成代码。但两者有一处关键差别——ASN.1允许多种编码方法,可以根据用途来选择。 Canonical Encoding Rules(CER)是其中的一种编码方式,其强制实行严格的编码规则,这对数字签名来说很关键,因为稍有差异就意味着很大的区别,其他可用的编码方式还有Packed Encoding Rules(PER)。 XML Encoding Rules(XER)允许将数据编码成XML,ASN.1也就成了与XML Schema并列的选项。Fast Web Services技术就能把XML Schemas映射成ASN.1,然后用ASN.1在端点之间进行编码效率更高的通信。
还有一种技术与Google的Protocol Buffers相似,那就是Facebook的Thrift,它的工作原理也差不多(见Protocol Buffers与Thrift的逐点对比)。Binary XML也是一种不太成功的类似技术,它已经在XML界酝酿了很久,但成功仍然遥遥无期。Erlang的创造者Joe Armstrong也在回答关于Protocol Buffers的问题时提到可以把UBF用作一种二进制格式直接传输程序字节码,无需解析。
这些技术共同的目标都是提高效率。有人可能觉得在线路上传输的数据量不是问题,因为有数据压缩技术。然而压缩/解压缩只是在使用数据前后执行的额外步骤,实际的解析过程中使用的仍然是没压缩的大量数据。对于XML来说,意味着一次又一次重复地读取同样的元素标签——简直与Protocol Buffers的数字标签没法比。当然,改善的程度取决于实际的格式。主要由字符串组成的格式效果就没有主要由数字数据组成的格式那么显著。
Mark Pilgirm也整理了一份对Protocol Buffer的反响。还有一个值得注意的方面,从Protocol Buffers身上可以看出一个RPC系统的蛛丝马迹。虽然目前还没有向大众公开,但在Steve Vinoski的博客上有一位Google的员工提到,Google内部确有这样一个RPC系统在担当重任。
你是否遇到过出于效率原因而考虑二进制格式的时候?如果是,你是自己搞一套还是找现有的技术?
阅读英文原文: Google Introduces Binary Encoding Format: Protocol Buffers