シリアル化技術 ProtoBuf
ProtoBuf :https://developers.google.cn/protocol-buffers
1. シリアル化とは
オブジェクトのコンテンツをデータ ストリームに変換します。
これに対応するのが逆シリアル化です。データ ストリームからデータを読み取り、それをオブジェクトに変換して戻します。
シリアル化と逆シリアル化は、多くの場合、特定の形式に従って動作します。
一般的なシリアル化には、オブジェクトの XML、JSON、バイナリ ストリームへの変換が含まれます。
特徴 | XML | JSON | プロトバッファ |
---|---|---|---|
データ構造 | 複雑 | 短い答え | より複雑 |
保管方法 | 文章 | 文章 | バイナリ |
保存サイズ | 大きい | 一般的 | 小さい |
解決速度 | 遅い | 一般的 | 素早い |
言語サポート | 多くの | 多くの | C/Java/py |
開発が簡単 | 問題 | 短い答え | 短い答え |
2. クロスプラットフォームのシリアル化
私の理解では、シリアル化はクロスプラットフォーム向けであり、異なるプラットフォームは相互に通信する必要があり、オブジェクトのシリアル化は相互のルールに従う必要があります。
一般に、クロスプラットフォームのものには、明らかにフィルタリングするための中間量が必要です。たとえば、Java クロスプラットフォームでは、テンプレートに相当するクラス ファイルが必要です。Thrift クロスプラットフォームの rpc では、フォーマット ファイル .thrift を定義する必要があります。同様に、 ProtoBuf は、クロスプラットフォームのシーケンス ツールも定義する必要があります。.proto
3. インストール
私はWindowsでテスト済みの直接ダウンロード対応バージョンですhttps://github.com/protocolbuffers/protobuf/releases/tag/v21.4
環境変数をインストールしてバージョン情報を実行するとOKということになります
C:\Users\sff>protoc --version
libprotoc 2.5.0
4. テンプレート学習
タイプスタディ
https://developers.google.cn/protocol-buffers/docs/proto
// 声明语法开头
syntax = "proto2";
//避免在 Protocol Buffers 名称空间以及非 Java 语言中的名称冲突。
package tutorial;
option java_multiple_files = true;
// java 对应的包和类
option java_package = "com.example.tutorial.protos";
//。如果你没有java_outer_classname明确给出a,它将通过将文件名转换为大写驼峰式来生成
option java_outer_classname = "AddressBookProtos";
message Person {
//标准的简单数据类型可用作字段类型 optional: 该字段可以设置也可以不设置 required:必须提供该字段的值,否则该消息将被视为“未初始化”
// repeated:该字段可以重复任意次数 required字段是非常不受欢迎的
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
Java コードを生成します (他の言語のコードも生成できます)
protoc addressbook.proto --java_out=D:\Resource\FrameMiddleware\proto\template
標準的なメッセージメソッド
各メッセージおよびビルダー クラスには、メッセージ全体を検査または操作できる次のような他のメソッドも多数含まれています。
isInitialized()
: 必須フィールドがすべて設定されているかどうかを確認します。toString()
: 人間が判読できるメッセージ表現を返します。特にデバッグに役立ちます。mergeFrom(Message other)
: (ビルダーのみ) の内容をother
このメッセージにマージし、単一のスカラー フィールドを上書きし、複合フィールドをマージし、繰り返しフィールドを連結します。clear()
: (ビルダーのみ) すべてのフィールドをクリアして空の状態に戻します。
これらのメソッドは、Message
すべての Java メッセージおよびビルダーによって共有されるインターフェースを実装します。詳細については、完全な API ドキュメントをMessage.Builder
参照してください。Message
解析とシリアル化
最後に、各プロトコル バッファー クラスには、プロトコル バッファーバイナリ形式を使用して選択したタイプのメッセージを読み書きするためのメソッドがあります。これらには次のものが含まれます。
byte[] toByteArray();
: メッセージをシリアル化し、生のバイトを含むバイト配列を返します。static Person parseFrom(byte[] data);
: 指定されたバイト配列からメッセージを解析します。void writeTo(OutputStream output);
: メッセージをシリアル化して に書き込みますOutputStream
。static Person parseFrom(InputStream input);
: から読み取り、解析しますInputStream
。
5. テスト
生成されたコードのインポート、Maven の追加
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.30.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.30.2</version>
</dependency>
<!-- 用于对比测试-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
Javaのテストコード
public class Main {
public static void main(String[] args) {
Person build = Person.newBuilder().setEmail("aaaaa").setName("zhangsan").setId(10).build();
System.out.println(build);
byte[] bytes = build.toByteArray();
System.out.println("bp size =" + bytes.length + "B");
PersonB personB = new PersonB("aaaaa", "zhangsan", 10);
byte[] bytes1 = JSONObject.toJSONString(personB).getBytes();
System.out.println(JSONObject.toJSONString(personB));
System.out.println("fastjson size =" + bytes1.length + "B");
}
}
結果
name: "zhangsan"
id: 10
email: "aaaaa"
bp size =19B
{
"email":"aaaaa","id":10,"name":"zhangsan"}
fastjson size =43B
実際のテストではその差は半分ですが、私のテストは厳密性が低いだけです。。。。。
6.アブロ
pb と比較すると、Avro は Java で書かれており、クロス言語シリアル化ツールでもあり、ルーチンはほぼ同じです