JSON XML 編寫簡單废境,語義性更強(qiáng)豺鼻,protobuf編寫雖然復(fù)雜,但是序列化與反序列化速度更快薛窥,生成的二進(jìn)制數(shù)據(jù)量更小。
第 7 章 Google Protobuf
7.1 編碼和解碼的基本介紹
- 編寫網(wǎng)絡(luò)應(yīng)用程序時眼姐,因?yàn)閿?shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)亩际嵌M(jìn)制字節(jié)碼數(shù)據(jù)拆檬,在發(fā)送數(shù)據(jù)時就需要編碼,接收數(shù)據(jù) 時就需要解碼 [示意圖]
-
codec(編解碼器) 的組成部分有兩個:decoder(解碼器)和 encoder(編碼器)妥凳。encoder 負(fù)責(zé)把業(yè)務(wù)數(shù)據(jù)轉(zhuǎn)換成字節(jié) 碼數(shù)據(jù)竟贯,decoder 負(fù)責(zé)把字節(jié)碼數(shù)據(jù)轉(zhuǎn)換成業(yè)務(wù)數(shù)據(jù)
image.png
7.2 Netty 本身的編碼解碼的機(jī)制和問題分析
- Netty 自身提供了一些 codec(編解碼器)
- Netty 提供的編碼器 StringEncoder,對字符串?dāng)?shù)據(jù)進(jìn)行編碼 ObjectEncoder逝钥,對 Java 對象進(jìn)行編碼 ...
- Netty 提供的解碼器 StringDecoder, 對字符串?dāng)?shù)據(jù)進(jìn)行解碼 ObjectDecoder屑那,對 Java 對象進(jìn)行解碼 ...
- Netty 本身自帶的 ObjectDecoder 和 ObjectEncoder 可以用來實(shí)現(xiàn) POJO 對象或各種業(yè)務(wù)對象的編碼和解碼,底層使用的仍是 Java 序列化技術(shù) , 而 Java 序列化技術(shù)本身效率就不高艘款,存在如下問題 無法跨語言 序列化后的體積太大持际,是二進(jìn)制編碼的 5 倍多。 序列化性能太低
- => 引出 新的解決方案 [Google 的 Protobuf]
7.3 Protobuf
- Protobuf 基本介紹和使用示意圖
- Protobuf 是 Google 發(fā)布的開源項(xiàng)目哗咆,全稱 Google Protocol Buffers蜘欲,是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲格式, 可以用于結(jié)構(gòu)化數(shù)據(jù)串行化晌柬,或者說序列化姥份。它很適合做數(shù)據(jù)存儲或 RPC[遠(yuǎn)程過程調(diào)用 remote procedure call ] 數(shù)據(jù)交換格式 。 目前很多公司 http+json tcp+protobuf
- 參考文檔 : https://developers.google.com/protocol-buffers/docs/proto 語言指南
- Protobuf 是以 message 的方式來管理數(shù)據(jù)的.
- 支持跨平臺年碘、跨語言澈歉,即[客戶端和服務(wù)器端可以是不同的語言編寫的] (支持目前絕大多數(shù)語言,例如 C++屿衅、 C#埃难、Java、python 等)
- 高性能,高可靠性
- 使用 protobuf 編譯器能自動生成代碼涡尘,Protobuf 是將類的定義使用.proto 文件進(jìn)行描述忍弛。說明,在 idea 中編 寫 .proto 文件時考抄,會自動提示是否下載 .ptotot 編寫插件. 可以讓語法高亮剧罩。
- 然后通過 protoc.exe 編譯器根據(jù).proto 自動生成.java 文件
-
protobuf 使用示意圖
image.png
7.4 Protobuf 快速入門實(shí)例 編寫程序,使用 Protobuf 完成如下功能
- 客戶端可以發(fā)送一個 Student PoJo 對象到服務(wù)器 (通過 Protobuf 編碼)
- 服務(wù)端能接收 Student PoJo 對象座泳,并顯示信息(通過 Protobuf 解碼)
導(dǎo)入maven
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.6.1</version>
</dependency>
Student.proto
syntax = "proto3"; //版本
option java_outer_classname = "StudentPOJO";//生成的外部類名,同時也是文件名
//protobuf 使用 message 管理數(shù)據(jù)
message Student { //會在 StudentPOJO 外部類生成一個內(nèi)部類 Student幕与, 他是真正發(fā)送的 POJO 對象
int32 id = 1; // Student 類中有 一個屬性 名字為 id 類型為
int32(protobuf 類型) 1 表示屬性序號挑势,不是值 string name = 2; }
IMG_2241(20201129-113132).JPG
IMG_2242(20201129-113204).JPG
案例1
NettyClient
NettyClientHandler
image.png
案例2
syntax = "proto3";
option optimize_for = SPEED; // 加快解析
option java_package="com.qiz.codec2"; //指定生成到哪個包下
option java_outer_classname="MyDataInfo"; // 外部類名
//protobuf 可以使用message 管理其他的message
message MyMessage {
//定義一個枚舉類型
enum DataType {
StudentType = 0; //在proto3 要求enum的編號從0開始
WorkerType = 1;
}
//用data_type 來標(biāo)識傳的是哪一個枚舉類型
DataType data_type = 1;
//表示每次枚舉類型最多只能出現(xiàn)其中的一個, 節(jié)省空間
oneof dataBody {
Student student = 2;
Worker worker = 3;
}
}
message Student {
int32 id = 1;//Student類的屬性
string name = 2; //
}
message Worker {
string name=1;
int32 age=2;
}
image.png
image.png
image.png
image.png