在Kafka中,發送的消息是字節數組,所以就須要一個方法來將消息對象序列化爲字節數組,在消費者端再反序列化爲對象。最經常使用的序列化格式就是JSON了。雖然JSON對人類很是友好,可是對於機器來講,更容易進行序列化和反序列化的格式仍是二進制的格式。git
Protobuf(Protocol buffers)是由Google開發的一種二進制協議,用於對結構化數據進行序列化和反序列化。這種格式佔用空間更少,更加簡單易於維護,同時擁有更好的性能。對於機器之間的通訊,Protobuf是比XML和JSON等格式更好的一種選擇。github
Protobuf的使用相比之下更加複雜,須要編寫.proto
格式的文件來定義數據格式,以後經過protoc
編譯器將其編譯到對應的語言,以後再在程序中引用。golang
首先就是安裝protoc
編譯器,這個編譯器能夠直接到github上下載二進制包,解壓到對應位置並設置PATH
便可。shell
以後就是安裝對應語言的客戶端,對於golang,執行下面兩條語句安裝就能夠了:數組
go get github.com/golang/protobuf/proto go get github.com/golang/protobuf/protoc-gen-go
以後新建一個.proto
文件,在其中定義消息的格式:性能
syntax = "proto3"; package test; option go_package = "proto/test"; message Award { int64 uid = 1; int64 awardId = 2; string userName = 3; }
而後使用protoc
編譯器將其編譯到go文件就好了:ui
protoc --go_out=. proto/*.proto
在go程序中引入生成的包就能夠進行序列化和反序列化了:google
import pb "proto/test" func marshal() { award := &pb.Award{ Uid: 628, AwardId: 1, UserName: "Haruka", } msg, err := proto.Marshal(award) } func unmarshal() { award := &pb.Award{} if err := proto.Unmarshal(msg.Value, award); err != nil { panic(err) } }
proto3
語言在.proto
文件的第一行就是syntax = "proto3";
,用於聲明該文件是proto3
版本的。以後能夠聲明package
用於避免命名衝突,最後就能夠定義message
了。url
message
的每一個字段都要分配一個惟一的ID,最小是1
最大是2^29 - 1
,同時不能使用 1900019999的ID。ID能夠任意分配,可是115只會佔用1個字節,而16~2047會佔用2個字節,所以應儘可能從小開始分配,並將小的分配給最常常出現的字段。code
可使用reserved
來對字段名和ID進行保留,通常用於爲將來新增字段保留,或者保留刪除字段來避免以後的字段使用,防止發生衝突:
message Foo { reserved 2, 15, 9 to 11; reserved "foo", "bar"; }
字段的類型默認是singular,也就是隻能出現一次或0次,若是在字段聲明前加上repeated
的話就能夠出現屢次。
protobuf的標量類型有如下幾種:double
float
int32
int64
uint32
uint64
sint32
sint64
fixed32
fixed64
sfixed32
sfixed64
bool
string
bytes
。
protobuf中還可使用枚舉和複合類型。例如能夠經過import "google/protobuf/timestamp.proto"
來使用timestamp類型。
protobuf數據類型的默認值規則以下,若是一個字段被設置爲默認值,則其不會被序列化:
string
bytes
類型默認爲空bool
類型默認爲false
0
0
message SearchRequest { enum Corpus { option allow_alias = true; UNIVERSAL = 0; WEB = 1; TEST = 1; IMAGES = 2; } Corpus corpus = 4; }
經過enum
來聲明一個枚舉,注意枚舉中必需要有0
值用來做爲默認值,同時0
值應該是第一個元素,以與proto2
兼容。經過option allow_alias = true;
來容許兩個枚舉元素有相同的值,即這兩個元素能夠相互替代。
在一個message
中,能夠嵌入其餘的message
做爲複合類型:
message SearchResponse { repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; }
在protobuf
中還有其餘高級類型,如Any
oneof
map
等,就不詳細介紹了。