當前位置:
首頁 > 知識 > 應用Protocol Buffers替代JSON的五個理由

應用Protocol Buffers替代JSON的五個理由

應用Protocol Buffers替代JSON的五個理由

Python部落(python.freelycode.com)組織翻譯,禁止轉載,歡迎轉發。

面向服務的體系架構作為一種從大規模應用中提取需求的可靠手段,緩解了應用規模增長帶來的痛苦,因此在Ruby和Rails開發社區中享有很好的聲譽。這些新開發的小型服務一般還在使用Rails或者Sinatra,並且用JSON通過HTTP進行交互。雖然JSON作為數據交換格式有很多顯著的優點——可讀性強,容易理解,應用性好——但它也有自己的弊端。

在那些瀏覽器和JavaScript並不直接消耗數據的服務——特別在內部服務這塊——像Google『s Protocol Buffers這種結構型編碼的數據格式會是比JSON更好的選擇。如果你以前從未接觸過Protocol Buffers,不用擔心——接下來我會簡單介紹它們在Ruby中的用法,然後告訴你為什麼要應用Protocol Buffers替代JSON的五個原因。

應用Protocol Buffers替代JSON的五個理由

簡單介紹Protocol Buffers

首先,什麼是Protocol Buffers? 官方文檔中是這樣定義的:

「Protocol Buffers 是一種高效可擴展的結構型數據編碼格式。」

Google開發Protocol Buffers為了用於他們自己的內部服務。它是一種二值編碼格式,能讓你用某種規範語言給數據指定一個結構對象,像這樣:

應用Protocol Buffers替代JSON的五個理由

你可以在命名空間中打包信息或者像上面代碼那樣在頂層進行聲明。這段代碼為一個Person類型定義了對象集合,這個類型有三個屬性:id, name 和 email 。除了屬性,你還可以指定屬性的類型來規定數據的編碼方式和傳輸方式——上面例子中我們看到有int32和string類型。用關鍵字來定義數據結構(像required和optional),同時屬性會做上編號,以便反向兼容,這點在後面會詳細提到。

Protocol Buffers規範語言支持多種版本:Java,C,Go等等,大部分流行的編程語言都能支持。Ruby當然也在其中,而且多種不同Gems能夠支持應用Protocol Buffers。這就意味著實現的編程語言不同也能用同一種規範在系統間傳輸數據。

舉個例子,安裝ruby-protocol-buffers 給Ruby Gem安裝了一個叫做ruby-protoc的程序,能夠結合Protocol Buffers的主庫(在OSX系統中為brew install protobuf命令)自動生成底層類文件用來編解碼數據。給ruby-protoc程序輸入proto文件會生成如下Ruby類:

應用Protocol Buffers替代JSON的五個理由

可以看到通過這種對象集合,我們能自動得到一個類用來把數據轉換成Protocol Buffer格式(更多細節可以查看Gem中ProtocolBuffers::Message基類的代碼文檔)。現在我們已經對此有了初步的了解,下面我將更深入地說明應用Protocol Buffers替代JSON的五個原因。

#1. 對象集合很實用

有一個諷刺的事實是,我們仔細地在資料庫中建立我們的數據模型,通過維護層層代碼來保證這些數據模型不受破壞,卻在服務間交換數據的時候置之不顧。而且經常情況下我們在系統間的數據交界處都依賴不統一的代碼,這就導致數據的重要結構丟失。如果把你的數據對象按照語義結構打包在proto格式中,那麼應用間交換的數據則能保證不被丟失,數據交界處也能保證規則的統一。

#2. 反向兼容很輕鬆

在proto格式的定義中經過編號的屬性可以滿足版本檢查的需求,這也是設計和應用Protocol Buffers的明顯動機之一。就像官方文檔所說,這個協議的設計一部分就是為了避免檢查協議版本時寫出一堆不夠簡潔的代碼,像這樣:

應用Protocol Buffers替代JSON的五個理由

有了屬性編號,我們不再需要更改代碼以反向兼容舊版本。如官方文檔所描述的,一旦Protocol Buffers被應用:

「新的域可以被輕鬆添加,而且那些不需要檢查數據的中間級服務也能在不知道所有屬性信息的條件下很容易地解析和傳遞這些數據的屬性信息。」

有了部署多個JSON服務的經驗以後,我十分清楚更新對象集合和反向兼容過程中遇到的各種弊端,所以我相信屬性編號能夠解決這些弊端,讓升級服務變得更簡單。

#3. 更少的樣板代碼

除了版本檢查麻煩和缺少反向兼容這些弊端外,HTTP服務中JSON端點還一般依賴專門手寫的樣板代碼來處理Ruby對象通過JSON編解碼的過程。解析器和顯示器的類經常包含隱藏的邏輯,暴露出手動解析每個新數據類型時容易出錯的弱點,然而當應用Protocol Buffers生成一個底層類(一個我們一般不會去動的類)的時候這些問題都能輕鬆解決。當對象集合需要更新時,我們也可以用proto生成的類解決相應問題,使我們能集中精力在開發應用和產品本身。

#4. 關鍵字和可擴展性

在Protocol Buffers定義中像required,optional,repeated這些關鍵字都十分有用,能讓我們在對象集合層面定義數據的結構,而類的工作細節在不同的編程語言下都會自動幫你處理。比如,Ruby的protocol_buffers庫會在你嘗試建立一個沒有required屬性的對象實例時報錯。我們也可以通過新增屬性編號為該屬性更改required或者optional屬性。有了這種基於數據語義的靈活性,序列化編碼格式將變得更加實用。

我們也可以把proto定義嵌套在其他定義中,所以我們也可以用一般的Request和Response結構控制其他數據結構的傳輸,使服務間的數據傳輸變得真正的靈活和安全。像Riak資料庫系統就已經把Protocol Buffers應用到十分成熟的地步,我推薦大家去了解下它們。

#5. 簡單的語言互操作性

因為Protocol Buffes可以用不同語言實現,它能使多語言應用的互操作性在我們的架構下變得非常簡單。如果我們用Java或Go建立了一個新服務,或甚至和Node,Clojure或Scala編寫的後端進行數據交換,我們都可以簡單地把proto文件交給目標語言的代碼生成器,而這些架構間的互操作性和安全性都能得到保證。在目標語言的代碼實現中,平台專有的數據類型可以直接為你處理好,省去JSON編解碼體系中屬性匹配和數據類型匹配的時間和精力,讓我們能專註於解決自己的問題。

什麼時候JSON會是更好的選擇呢?

確實有些時候JSON仍比Protocol Buffers更適合需要,包括以下幾種情況:

  • 希望代碼可讀性更強

  • 瀏覽器直接面向服務數據

  • 服務端應用是基於JavaScript

  • 不準備把數據模型和對象集合綁定

  • 帶寬不足以增加更多的開發工具

  • 運行不同類型的網路服務帶來的工作負荷已經過大

可能情況還有更多。最終需要永遠牢記的是利弊的權衡,盲目選擇一項技術很難達到成功。

結論

Protocol Buffers在內部服務的數據傳輸方面和JSON相比具有多項優勢。雖然不能完全取代JSON,尤其對於瀏覽器需要直接面向服務數據的時候,但是Protocol Buffers在其他方面比如像編解碼速度、傳輸數據所佔空間大小等都具有更好的表現。

你會從大規模應用中提取什麼服務呢?你會選擇JSON還是Protocol Buffers呢?我們期待你的經驗分享並在評論區進行留言。

英文原文:https://codeclimate.com/blog/choose-protocol-buffers/
譯者:GeeKnight

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

PEP 541:Python包名衝突了怎麼辦?

TAG:Python部落 |