说到数据格式化框架,就不得不提到 Google 的 Protocol Buffers,Facebook 的 Thrift,还有 Apache Hadoop 推出的 Avro。Microsoft 最近开源的 Bond 也是一种用于数据格式化的可扩展框架,其适用的应用场景包括服务间通信、大数据存储和处理等。
为什么会有这么多关于数据格式处理的框架?它们都在解决什么问题呢?我们先来观察一下典型的服务间通信的结构。
通常,在设计服务间通信时,我们所要面对的基本问题有:
- 如何传输数据?
- 使用什么协议通信?
- 数据以何种格式表达?
- 在服务端如何处理数据请求?
- 数据在服务端如何存储?
- 请求消息如何路由或转发?
随着服务系统架构的不断演进,我们会面对更多的问题:
- 适应架构演进的能力
- 适应集群扩展的能力
- 灵活性
- 延时
- 简单
那么,以前我们都是在用什么技术来解决这些问题的呢?
- C 语言的动态结构体二进制传输
- DCOM, COM+
- CORBA
- SOAP
- XML, JSON
都是听起来很熟悉的名字。实际上,C 结构体仍然被广泛地应用于网络底层通信,DCOM, CORBA, SOAP 正逐步退出历史舞台。目前,最流行的就是基于 XML 或 JSON 的序列化机制。
但使用 XML 和 JSON 时也会面对一些问题:
- 通信协议需要额外描述
- 需要维护服务端和客户端两侧契约代码
- 需要为设计的协议编写包装类
- 需要为不同编程语言编写实现
- 承担解析 XML 和 JSON 较高的开销
- 存储空间占用相对较多
那么,对于这些数据处理和序列化框架,从软件设计人员的角度来看,我们最需要的到底是什么呢?
- 多语言间的透明性
- 时间和空间效率
- 支持快速开发
- 能利用已有的类库
所以,业界著名公司的开发人员分别推出了不同的框架,以期解决这些问题。包括 Google 的 Protocol Buffers,Facebook 的 Thrift,Apache Hadoop 的 Avro,和 Microsoft 的 Bond。
这些框架的一些共性:
- 使用 IDL 定义,IDL (Interface Description Language)
- 性能较高
- 支持版本演进
- 采用二进制格式
这些框架的典型使用过程:
- 编写类似于结构体的消息格式定义,使用类似于 IDL 的语言定义。
- 使用代码生成工具,生成目标语言代码。
- 虽然生成了许多代码,但代码的可读性比较高。
- 在程序中直接使用这些代码。
- 生成的代码不允许编辑。
也就是说,用户首先需要定义数据结构,然后生成可以有效读写这些数据结构的代码,再将代码嵌入到服务端与客户端的代码中使用。
例如,下面使用 Protocol Buffers 的定义搜索请求消息 search.proto。
package serializers.protobuf.test; message SearchRequest { required string query = 1