Protocol Buffer

Protocol Buffer 初探

吳唯碩 2020/07/24 11:18:10
1846

Protocol Buffers

什麼是Protocol Buffers?

Protocol buffers 是由Google所推出的傳遞資料的格式,可以把它想像成XML或者是Json,但是更小、更快、更簡潔。可以幫助你節省網路資源,且你只需要定義一次資料結構,透過protocol這個套件,能夠自動生成你使用程式語言的檔案,讓你直接在 專案內使用,目前可以支援自動產生code的語言,有JavaPythonObjective-CC++,但是在最新的proto3 這個版本後又多新增了DartGoRubyC#

 

比較JsonProtocol BufferXML

JsonXML 比較下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 目前仍是首選。

 

吳唯碩