Protocol Buffer 初探
Protocol Buffers
什麼是Protocol Buffers?
Protocol buffers 是由Google所推出的傳遞資料的格式,可以把它想像成XML或者是Json,但是更小、更快、更簡潔。可以幫助你節省網路資源,且你只需要定義一次資料結構,透過protocol這個套件,能夠自動生成你使用程式語言的檔案,讓你直接在 專案內使用,目前可以支援自動產生code的語言,有Java、Python、Objective-C、C++,但是在最新的proto3 這個版本後又多新增了Dart、Go、Ruby、C#。
比較Json、Protocol Buffer、XML
與Json及XML 比較下Protocol Buffer有資料輕量化、效能較高的優點,但可讀性低,需要透過程式進行解析,無法在瀏覽器端或者是終端機端理解資料,在大型網站上可以使用Protocol Buffer進行資料傳遞,但是在傳統網站或小型網站可能會花費過多的時間與開發成本。
Protocol Buffer序列化及Java序列化比較
Protocol Buffer的傳遞,是將資料序列化之後,進行資料的傳遞,相對於Java本身有的序列化機制能夠將物件壓的更小,透過以下程式碼我們可以發現,兩個相同物件ProtocolBuffer的陣列長度比起原本Java提供序列化的陣列長度還要小很多。
StudentData studentData = StudentData.newBuilder().setId(10151101)
.setName("WilsonWu")
.setEmail("wilson.wu@thinkpower-info.com")
.setHeight(170.5)
.setWeight(65)
.build();
Student student = new Student();
student.setId(10151101);
student.setName("WilsonWu");
student.setEmail("wilson.wu@thinkpower-info.com");
student.setHeight(170.5);
student.setWeight(65);
byte[] studentDataByte = studentData.toByteArray();
byte[] objectToByteArray = objectToBytes(student);
LOGGER.info("Protocol byte :"+studentDataByte.length);
LOGGER.info("Java byte :"+objectToByteArray.length);
2020-06-23 13:49:33.925 INFO 89812 --- [nio-8080-exec-3] c.p.demo.controller.UserController : Protocol byte :64
2020-06-23 13:49:33.926 INFO 89812 --- [nio-8080-exec-3] c.p.demo.controller.UserController : Java byte :176
Java Generate Protocol Buffers
安裝Protocol Buffer generate Code Tool
Step1:下載需要用套件。
Windows系統
下載需要安裝的包
Mac 系統
在 Terminal 下 $brew install protobuf (需要先裝home brew 套件)
Step2:確認是否安裝。
1.在 Terminal 下 $protoc —version 確認是否有安裝成功。
自動化產出JavaCode
Step1:定義.proto文件。
// 撰寫格式是 Proto v3。
syntax = "proto3";
// 定義產出package名稱
package com.protobuf.demo.proto;
// 定義產出JavaClass名稱(預設為 messageName+OuterClass ex:StudentDataOuterClass)
option java_outer_classname = "StudentProto";
// 定義Data名稱
message StudentData {
int64 id = 1;
string name = 2;
string email = 3;
double height = 4;
double weight = 5;
}
Step2:將.proto文件放置下圖路徑。
Step3:build.gradel加入.proto 相關 jar 。
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.12.2'
compile group: 'com.googlecode.protobuf-java-format', name: 'protobuf-java-format', version: '1.4'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
Step4:利用cmd 進入該專案資料夾層後,下
$protoc -I=src/main/resources/proto --java_out=src/main/java Student_data.proto
- 第一個參數 -I .proto 文件所在資料夾。
- 第二個參數 --java_out 產出JavaCode資料夾
- 第三個參數最後加上要產出的.proto文件 Student_data.proto
進行ProtocolBuffer 序列化及反序列化
Step1:建立一個Student序列化及反序列化過程
P.S. 一般序列化及反序列化是分開的,由Server端一方發出序列化過後的Byte陣列,由另一方進行反序列化解析,這裡為了簡化而寫在同一個方法內。
LOGGER.info("建構StudentData 開始.....");
StudentData studentData = StudentData.newBuilder().setId(10151101)
.setName("WilsonWu")
.setEmail("wilson.wu@thinkpower-info.com")
.setHeight(170.5)
.setWeight(65)
.build();
System.out.println(studentData);
LOGGER.info("建構StudentData 結束.....");
LOGGER.info("StudentData 序列化 開始.....");
byte[] studentDataByte = studentData.toByteArray();
System.out.println(Arrays.toString(studentDataByte));
LOGGER.info("StudentData 序列化 結束.....");
LOGGER.info("StudentData 反序列化開始.....");
StudentData parseStudentData = null;
try {
parseStudentData = studentData.parseFrom(studentDataByte);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.println(parseStudentData);
LOGGER.info("StudentData 反序列化結束.....");
2020-06-23 14:05:22.988 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : 建構StudentData 開始.....
id: 10151101
name: "WilsonWu"
email: "wilson.wu@thinkpower-info.com"
height: 170.5
weight: 65.0
2020-06-23 14:05:23.336 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : 建構StudentData 結束.....
2020-06-23 14:05:23.336 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : StudentData 序列化 開始.....
[8, -67, -55, -21, 4, 18, 8, 87, 105, 108, 115, 111, 110, 87, 117, 26, 29, 119, 105, 108, 115, 111, 110, 46, 119, 117, 64, 116, 104, 105, 110, 107, 112, 111, 119, 101, 114, 45, 105, 110, 102, 111, 46, 99, 111, 109, 33, 0, 0, 0, 0, 0, 80, 101, 64, 41, 0, 0, 0, 0, 0, 64, 80, 64]
2020-06-23 14:05:23.354 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : StudentData 序列化 結束.....
2020-06-23 14:05:23.355 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : StudentData 反序列化開始.....
id: 10151101
name: "WilsonWu"
email: "wilson.wu@thinkpower-info.com"
height: 170.5
weight: 65.0
2020-06-23 14:05:23.357 INFO 95684 --- [nio-8080-exec-2] c.p.demo.controller.UserController : StudentData 反序列化結束.....
總結:
透過Protocol Buffer資料傳遞格式,我們能夠提高大型系統及分散式系統的效能,但是對於一般小型專案或網站而言,Json 目前仍是首選。