在Ruby和Rails开发者中,面向服务(Service-Oriented)架构有一个当 之无愧的名声,它是一个缓解程序规模恶性增长的一个强有力的途径,可在大量应用程序中提取关注点。这些新生小巧的服务通常继续使用Rails或 Sinatra,并使用JSON在HTTP上通信。尽管JSON作为一个数据相互交换格式,有很多优点:人类可读、可理解,并通常表现出色。 浏览器和JS并不直接处理数据--尤其是遇到内部服务时。我的观点是,结构化格式,例如谷歌的Protocol Buffers,是一个比JSON在编码方面更好的选择。如果你从来没有使用过Protocol Buffers,你可以参看 这里。不要担心,在说明为什么要选择Protocol Buffers而不是JSON之前,本文会简介如何使用在Ruby上使用它 。
Protocal Buffers的简短介绍首先,什么是Protocol Buffers?文档中说:
Google开发了Protocol Buffers使用于内部的服务。 它是一种二进制格式允许你使用规范的语言定义一个模式,例如:
你能在命名空间中封装他们或者用上面的方式在顶层声明他们。这个片段定义了Person数据类型的模式,有三个字段:id, name和email。除了命名字段,你能提供一个类型决定数据怎样编码和在线上发送,在上面我们看到有int32类型和string类型。还提供了关键字进行验证和结构化(required 和optional )。字段被编号,这有助于向后兼容,我将在以后详细的介绍。 Protocol Buffers规范已被多种语言实现:Java,C,Go等。如果你四处找找最现代的语言都有实现的方式。Ruby也不例外,有几个不同的Gems使用Protocol Buffers编码和解码数据。这就意味着,这个规范可以在不同语言实现的系统间传递数据。 例如,Ruby Gem安装被称为ruby-protoc的二进制可以和主Protocol Buffers库组合使用(在OSX中brew install protobuf),自动的产生桩类文件用于编码和解码数据。正在运行的二进制proto文件产生以下的Ruby类:
正如你所见,通过支持这种模式(Protocol Buffer格式),用来编码和解码信息,我们就能自动得到一个类(查看代码ProtocolBuffers::Message的基类在Gem中有更多细节的介绍)。我们已经看到了一些信息,那么就让我们再来仔细看看这些特征点,让我尝试说服你考虑Protocol Buffers——这里有5个理由。 原因 #1: 模式本身很不错有一种痛苦的讽刺指向一个事实,我们小心谨慎地在我们的数据库里面编写数据模型,维护各个层次的代码,保持这些数据模型处于控制之中,当我们想要发送数据连接到另一个服务的时候,要求所有的疑虑都要被考虑到。然而,我们往往依靠的是在边界上与我们的系统之间不一致的代码,我们的系统不能强制结构化我们的数据组件,这是如此的重要,编码的语义是你曾经的业务对象,在proto格式中,它足以帮助并保证应用程序之间的信号不会丢失,而界限就在你所创建并执行的业务规则。 原因 #2: 无偿地向后兼容被编号的字段在proto的定义中排除了所需的版本检查,这是其中一个被明确表述的动机(为什么这样设计和实现Protocol Buffers)。如同开发者文档中声明的那样,协议被设计成能在一定程度上避免出现像下面这样的“丑陋的代码”,下面的代码用来检测协议的版本:
同编号字段一样, 你必须改变编码习惯,朝着能向老版本维护和向后兼容的方向改变。正如在文档中的声明那样,曾经 Protocol Buffers 是这样被介绍的:
已经部署各种JSON的服务器已经遭受各种与发展模式以及向后兼容的相关问题。我现在深信编号字段能防止错误,并且能在新功能和服务的推出上做到简化。 原因 #3: 更少的样本代码除了显式的版本检查和缺乏后续的兼容性,JSON终端在HTTP上的基础服务通常依赖专门的手写样板代码去处理Ruby对象的编码和解码。解析和反解析类常常包含隐藏的业务逻辑,它暴露了手动解析每个新的数据类型的缺陷,当一个类通过Protocol Buffers产生(你一般就不会再去触碰它),它能提供大量相似的方法,还避免了大量头痛的事情。随着模式的发展,你将会用proto产生类(应当承认,一旦你更新他们),你可以把更多的空间留给你所关注的挑战(保持你的应用运行和持续构建产品)。 原因 #4: 验证和可扩展性required,optional 和 repeated关键字在Protocol Buffers中的定义是非常强大的。它们允许你去编码,在模式级别,形象化你的数据结构和去实现类怎样工作(每种编程语言处理)的细节。Ruby的protocol_buffers库将会提升异常,例如:如果一个对象实例没有填写必填的字段,你试着去对这样一个对象实例编码,就会提升异常。通过简单地编辑一个新的编号字段的值,你可以把一个字段从required变成optional或者反之亦然。有了这种灵活编码的语义序列化格式,大大增强了其功能。 因为你还可以嵌入proto,定义内部的其他成员,你也可以拥有通用的Request和Response结构,它还允许其他数据结构的传输并确保传输连接上,它为服务器间通讯实现真正的灵活性和安全的数据传输提供了机会。类似Riak的数据库系统使用Protocol Buffers有巨大的效果——因为有了一些启示,我建议重新审视那些接口。 原因#5:建议的语言互操作性 因为Protocol Buffers已经被多种语言实现,在你的架构中多语言混合的应用程序之间的互操作性变得更简单。如果你引入了一个新的服务在JAVA或者GO中,甚至和用Node或者Clojure或者Scala实现的后端通讯,你只需简单的把proto文件交给目标语言编写的代码生成器,你将在这些架构之间获得较好的安全和互操作性。平台特定数据类型的细节被目标语言处理,你将更多的关注你的问题的困难部分,而不是匹配字段和数据类型在JSON的编码和解码方案中。 什么时候更适合使用JSON?有些时候JSON比Protocol Buffers更适合,包括如下的场景:
可能还有更多的情况。最后,总之,这是很重要的在心里权衡和不要盲目的选择一项技术 |