一條消息數據,用protobuf序列化後的大小是json的10分之一,xml格式的20分之一,是二進制序列化的10分之一,整體看來ProtoBuf的優點仍是很明顯的。php
protobuf是google提供的一個開源序列化框架,相似於XML,JSON這樣的數據表示語言,詳情訪問protobuf的google官方網站。html
protobuf在google中是一個比較核心的基礎庫,做爲分佈式運算涉及到大量的不一樣業務消息的傳遞,如何高效簡潔的表示、操做這些業務消息在google這樣的大規模應用中是相當重要的。而protobuf這樣的庫正好是在效率、數據大小、易用性之間取得了很好的平衡。java
protobuf簡單總結以下幾點:python
1.靈活(方便接口更新)、高效(效率通過google的優化,傳輸效率比普通的XML等高不少);c++
2.易於使用;開發人員經過按照必定的語法定義結構化的消息格式,而後送給命令行工具,工具將自動生成相關的類,能夠支持java、c++、python等語言環境。經過將這些類包含在項目中,能夠很輕鬆的調用相關方法來完成業務消息的序列化與反序列化工做。git
3.語言支持;原生支持c++,java,pythongithub
我的總結的適用protobuf的場合:golang
1.須要和其它系統作消息交換的,對消息大小很敏感的。那麼protobuf適合了,它語言無關,消息空間相對xml和json等節省不少。
2.小數據的場合。若是你是大數據,用它並不適合。
3.項目語言是c++,java,python的,由於它們可使用google的源生類庫,序列化和反序列化的效率很是高。其它的語言須要第三方或者本身寫,序列化和反序列化的效率不保證。
4.整體而言,protobuf仍是很是好用的,被不少開源系統用於數據通訊的工具,在google也是核心的基礎庫。
此外,還有更牛叉的facebook的thrift,2007年由Facebook開發,以後在2008年加到Apache計劃中。是一個跨語言的輕量級RPC消息和數據交換框架,Thrift能生成的語言有: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml,這是它的一大優勢。編程
安裝 goprotobufjson
1.從 https://github.com/google/protobuf/releases 獲取 Protobuf 編譯器 protoc(可下載到 Windows 下的二進制版本
wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz tar zxvf protobuf-2.6.1.tar.gz cd protobuf-2.6.1 ./configure make make install protoc -h
2.獲取 goprotobuf 提供的 Protobuf 編譯器插件 protoc-gen-go(被放置於 $GOPATH/bin 下,$GOPATH/bin 應該被加入 PATH 環境變量,以便 protoc 可以找到 protoc-gen-go)
此插件被 protoc 使用,用於編譯 .proto 文件爲 Golang 源文件,經過此源文件可使用定義在 .proto 文件中的消息。
go get github.com/golang/protobuf/protoc-gen-go cd github.com/golang/protobuf/protoc-gen-go go build go install vi /etc/profile 將$GOPATH/bin 加入環境變量 source profile
3.獲取 goprotobuf 提供的支持庫,包含諸如編碼(marshaling)、解碼(unmarshaling)等功能
go get github.com/golang/protobuf/proto cd github.com/golang/protobuf/proto go build go install
使用 goprotobuf
這裏經過一個例子來講明用法。先建立一個 .proto 文件 test.proto:
package example; enum FOO { X = 17; }; message Test { required string label = 1; optional int32 type = 2 [default=77]; repeated int64 reps = 3; optional group OptionalGroup = 4 { required string RequiredField = 5; } }
編譯此 .proto 文件:
protoc --go_out=. *.proto
這裏經過 –go_out 來使用 goprotobuf 提供的 Protobuf 編譯器插件 protoc-gen-go。這時候咱們會生成一個名爲 test.pb.go 的源文件。
在使用以前,咱們先了解一下每一個 Protobuf 消息在 Golang 中有哪一些可用的接口:
每個 Protobuf 消息對應一個 Golang 結構體
消息中域名字爲 camel_case 在對應的 Golang 結構體中爲 CamelCase
消息對應的 Golang 結構體中不存在 setter 方法,只須要直接對結構體賦值便可,賦值時可能使用到一些輔助函數,例如:
msg.Foo = proto.String("hello")
消息對應的 Golang 結構體中存在 getter 方法,用於返回域的值,若是域未設置值,則返回一個默認值
消息中非 repeated 的域都被實現爲一個指針,指針爲 nil 時表示域未設置
消息中 repeated 的域被實現爲 slice
訪問枚舉值時,使用「枚舉類型名_枚舉名」的格式(更多內容能夠直接閱讀生成的源碼)
使用 proto.Marshal 函數進行編碼,使用 proto.Unmarshal 函數進行解碼
如今咱們編寫一個小程序:
/* # @Time : 2018/11/19 16:42 # @Author : Mickel Xiang # @File : test_protobuff.go # @Function: ----------- */ package main import ( "log" // 輔助庫 "github.com/golang/protobuf/proto" // test.pb.go 的路徑 "./protocol/example" ) func main() { // 建立一個消息 Test test := &example.Test{ // 使用輔助函數設置域的值 Label: proto.String("hello"), Type: proto.Int32(17), Optionalgroup: &example.Test_OptionalGroup{ RequiredField: proto.String("good bye"), }, } // 進行編碼 data, err := proto.Marshal(test) if err != nil { log.Fatal("marshaling error: ", err) } // 進行解碼 newTest := &example.Test{} err = proto.Unmarshal(data, newTest) if err != nil { log.Fatal("unmarshaling error: ", err) } // 測試結果 if test.GetLabel() != newTest.GetLabel() { log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) } }
轉自:http://blog.csdn.net/wenyiqingnianiii/article/details/52741312
ProtoBuf是Google開源的一套二進制流網絡傳輸協議,它獨立於語言,獨立於平臺。google 提供了多種語言的實現:java、c#、c++、Go 和Python,每一種實現都包含了相應語言的編譯器以及庫文件。因爲它是一種二進制的格式,比使用 xml 進行數據交換快許多。能夠把它用於分佈式應用之間的數據通訊或者異構環境下的數據交換。做爲一種效率和兼容性都很優秀的二進制數據傳輸格式,能夠用於諸如網絡傳輸、配置文件、數據存儲等諸多領域。
優勢:傳輸效率快(比xml和json快10-20倍),文檔型協議;
缺點:使用不太方便;
這裏簡單解釋一下什麼是文檔型協議,向咱們的xml和json通常在使用的時候都須要保存一份說明文檔和一個實際的java類,而protobuf在使用的時候其定義的格式就是說明文檔,簡單明瞭並且能夠將其編譯成各個平臺的類庫,以java平臺爲例,其編程成jar以後,若定義文件發生了變化,則在使用jar包的話就會報錯,必須從新編譯,這也就保證了App端與服務器端的協議統一性。
網絡傳輸協議實踐
因爲ProtoBuf的傳輸效率和文檔型協議的特性,公司產品選擇了Protobuf做爲網絡傳輸協議。下面我就以一個簡單的登陸操做,介紹一下對ProtoBuf的實際應用。
能夠看到在Protobuf中定義網絡請求,分爲兩個部分,請求部分和應答部分,其message request定義的是請求信息,而message response定義的是應答信息。
請求信息中的字段就是咱們請求中須要傳遞的字段,應答信息中的字段就是App端獲取的服務器端的應答信息集合。
每一個字段都有修飾符,那麼修飾符是作什麼的呢?
在protobuf中定義了三種修飾符,分別爲:required,optional,repeated。其中:
required:表示的是這個字段必需要傳遞,不可爲空;
optional:表示的是這個字段可傳可不傳,能夠爲空;
repeated:表示這個字段傳遞的是列表數據
在message的定義過程當中,message還能夠嵌套另外的message信息,好比應答信息中的UserStatus,其和java中對象的概念很相似。
(3)將proto文件編譯成jar包
這裏就不在具體介紹怎麼講proto文件編譯成jar了,google已經提供了相應的編譯工具。
(4)在Android代碼中使用
因爲咱們將proto文件編譯成了jar包,首先咱們須要將jar引入到咱們的工程,而後就可使用了。這裏簡單看一下具體的使用代碼。
能夠發現咱們在代碼中直接有對應的登陸請求message類,這樣咱們就能夠直接經過java類調用了,O(∩_∩)O哈哈~。
總結:
本文主要介紹了App開發過程當中常見了三種網絡傳輸協議,以及各自的優劣勢,還重點介紹了protobuf協議的使用方式等。固然了這裏我仍是比較推薦protobuf的。