使用 Protocol Buffers 代替 JSON 的五个原因

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。

国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html
内部邀请码:C8E245J (不写邀请码,没有现金送)
国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为中国PE第一股,市值超1000亿元。 

------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

在Ruby和Rails开发者中,面向服务(Service-Oriented)架构有一个当之无愧的名声,它是一个缓解程序规模恶性增长的一个强有力的途径,可在大量应用程序中提取关注点。这些新生小巧的服务通常继续使用Rails或Sinatra,并使用JSON在HTTP上通信。尽管JSON作为一个数据相互交换格式,有很多优点:人类可读、可理解,并通常表现出色。

浏览器和JS并不直接处理数据--尤其是遇到内部服务时。我的观点是,结构化格式,例如谷歌的Protocol Buffers,是一个比JSON在编码方面更好的选择。如果你从来没有使用过Protocol Buffers,你可以参看 这里。不要担心,在说明为什么要选择Protocol Buffers而不是JSON之前,本文会简介如何使用在Ruby上使用它 。

PBJSON

Protocal Buffers的简短介绍

首先,什么是Protocol Buffers?文档中说:

“Protocol Buffers是一种以有效并可扩展的格式编码结构化数据的方式。”

Google开发了Protocol Buffers使用于内部的服务。 它是一种二进制格式允许你使用规范的语言定义一个模式,例如:

?
1
2
3
4
5
message Person {
   required int32 id = 1;
   required string name = 2;
   optional string email = 3;
}

 

你能在命名空间中封装他们或者用上面的方式在顶层声明他们。这个片段定义了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类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env ruby
# Generated by the protocol buffer compiler. DO NOT EDIT!
require  'protocol_buffers'
 
# forward declarations
class  Person < ::ProtocolBuffers::Message;  end
     
class  Person < ::ProtocolBuffers::Message
   set_fully_qualified_name  "Person"
       
   required  :int32 :id 1
   required  :string :name 2
   optional  :string :email 3
end

正如你所见,通过支持这种模式(Protocol Buffer格式),用来编码和解码信息,我们就能自动得到一个类(查看代码ProtocolBuffers::Message的基类在Gem中有更多细节的介绍)。我们已经看到了一些信息,那么就让我们再来仔细看看这些特征点,让我尝试说服你考虑Protocol Buffers——这里有5个理由。

原因 #1: 模式本身很不错

有一种痛苦的讽刺指向一个事实,我们小心谨慎地在我们的数据库里面编写数据模型,维护各个层次的代码,保持这些数据模型处于控制之中,当我们想要发送数据连接到另一个服务的时候,要求所有的疑虑都要被考虑到。然而,我们往往依靠的是在边界上与我们的系统之间不一致的代码,我们的系统不能强制结构化我们的数据组件,这是如此的重要,编码的语义是你曾经的业务对象,在proto格式中,它足以帮助并保证应用程序之间的信号不会丢失,而界限就在你所创建并执行的业务规则。

原因 #2: 无偿地向后兼容

被编号的字段在proto的定义中排除了所需的版本检查,这是其中一个被明确表述的动机(为什么这样设计和实现Protocol Buffers)。如同开发者文档中声明的那样,协议被设计成能在一定程度上避免出现像下面这样的“丑陋的代码”,下面的代码用来检测协议的版本:

?
1
2
3
4
5
6
7
8
if  (version ==  3 ) {
   ...
else  if  (version >  4 ) {
   if  (version ==  5 ) {
     ...
   }
   ...
}

同编号字段一样, 你必须改变编码习惯,朝着能向老版本维护和向后兼容的方向改变。正如在文档中的声明那样,曾经 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更适合,包括如下的场景:

  • 你需要或者想让数据对人是可读的

  • 来自于服务的数据是直接发送到web浏览器

  • 你的服务端应用程序是用javaScript编写的

  • 你不准备把数据模型绑定到模式上

  • 你没有带宽添加另外一个工具到你的军火库

  • 运行不同类型的网络服务的运营负担过大

可能还有更多的情况。最后,总之,这是很重要的在心里权衡和不要盲目的选择一项技术

结论

Protocol Buffers提供了几种相对JSON在内部服务之间在线传输数据的引人注目的优势。并没有完全的替换JSON,特别是服务和web浏览器直接通讯的情况,Protocol Buffers提供了真正的优势不仅在上面概述的方法,也编解码的速度和数据大小上有更多的优势。

你可以从你的应用程序中提取出哪些服务?如果你今天不得不做出选择,你会选择JSON还是Protocol Buffers?让我们讨论讨论-我们愿意在下面的评论中听到更多关于你在使用JSON和Protocol Buffers上的经验。

 

目录
相关文章
|
JSON Java Devops
有了 Protocol buffer 还是用 JSON
Protocol buffer 这东西真的很轻便吗
148 0
|
2月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
44 1
|
17天前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
2天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
6天前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。
|
21天前
|
JSON JavaScript Java
在Java中处理JSON数据:Jackson与Gson库比较
本文介绍了JSON数据交换格式及其在Java中的应用,重点探讨了两个强大的JSON处理库——Jackson和Gson。文章详细讲解了Jackson库的核心功能,包括数据绑定、流式API和树模型,并通过示例演示了如何使用Jackson进行JSON解析和生成。最后,作者分享了一些实用的代码片段和使用技巧,帮助读者更好地理解和应用这些工具。
在Java中处理JSON数据:Jackson与Gson库比较
|
1月前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
1月前
|
JSON 前端开发 Java
【Spring】“请求“ 之传递 JSON 数据
【Spring】“请求“ 之传递 JSON 数据
84 2
|
2月前
|
存储 JSON Go
在Gin框架中优雅地处理HTTP请求体中的JSON数据
在Gin框架中优雅地处理HTTP请求体中的JSON数据
|
2月前
|
JSON JavaScript 数据格式
vue写入json数据到文本中+vue引入cdn的用法
vue写入json数据到文本中+vue引入cdn的用法
53 10