<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          什么?你竟然還不知道 Protobuf ?

          共 5641字,需瀏覽 12分鐘

           ·

          2020-07-27 09:10

          本文公眾號(hào)來(lái)源:JavaKeeper    作者:Java大猿帥
          ??? 局長(zhǎng)導(dǎo)讀:“

          Google Protocol Buffer( 簡(jiǎn)稱 Protobuf) 是 Google 公司內(nèi)部的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn) ,是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說(shuō)序列化(將 數(shù)據(jù)結(jié)構(gòu)或?qū)ο?轉(zhuǎn)換成 二進(jìn)制串 的過(guò)程 )。它很適合做數(shù)據(jù)存儲(chǔ)RPC 數(shù)據(jù)交換格式??捎糜谕ㄓ崊f(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式

          protocol buffers 誕生之初是為了解決服務(wù)器端新舊協(xié)議(高低版本)兼容性問(wèn)題,名字也很體貼,“協(xié)議緩沖區(qū)”。只不過(guò)后期慢慢發(fā)展成用于傳輸數(shù)據(jù)。

          筆者所在的360廣告投放,5億條商品信息的數(shù)據(jù)全部采用PB格式存儲(chǔ)、傳輸。

          Protobuf 的優(yōu)點(diǎn)

          • 更小——序列化后,數(shù)據(jù)大小可縮小約3倍

          • 更快——序列化速度更快,比xml和JSON快20-100倍,體積縮小后,傳輸時(shí),帶寬也會(huì)優(yōu)化

          • 更簡(jiǎn)單——proto編譯器,自動(dòng)進(jìn)行序列化和反序列化

          • 維護(hù)成本低——跨平臺(tái)、跨語(yǔ)言,多平臺(tái)僅需要維護(hù)一套對(duì)象協(xié)議(.proto)

          • 可擴(kuò)展——“向后”兼容性好,不必破壞已部署的、依靠“老”數(shù)據(jù)格式的程序就可以對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行升級(jí)

          • 加密性好——HTTP傳輸內(nèi)容抓包只能看到字節(jié)

            在傳輸數(shù)據(jù)量大、網(wǎng)絡(luò)環(huán)境不穩(wěn)定的數(shù)據(jù)存儲(chǔ)和RPC數(shù)據(jù)交換場(chǎng)景比較合適

          Protobuf 的不足

          • 功能簡(jiǎn)單,無(wú)法用來(lái)表示復(fù)雜的概念
          • 通用性較差,XML和JSON已成為多種行業(yè)標(biāo)準(zhǔn)的編寫工具,pb只是geogle內(nèi)部使用
          • 自解釋性差,以二進(jìn)制數(shù)據(jù)流方式存儲(chǔ)(不可讀),需要通過(guò).proto文件才可以

          官網(wǎng) Protocol Buffer Basics: Java https://developers.google.com/protocol-buffers/docs/javatutorial

          Hello World

          1. 定義 .proto 文件的消息格式(你希望存儲(chǔ)的數(shù)據(jù)格式描述文件)
          syntax = "proto2";

          package tutorial;

          option java_package = "com.example.tutorial";
          option java_outer_classname = "AddressBookProtos";

          //消息模型
          message Person {
          //消息對(duì)象的字段:字段修飾符+字段類型+字段名稱+標(biāo)識(shí)號(hào)(通過(guò)二進(jìn)制格式唯一標(biāo)識(shí)每個(gè)字段,不變可)
          required string name = 1;
          required int32 id = 2;
          optional string email = 3;

          enum PhoneType {
          MOBILE = 0;
          HOME = 1;
          WORK = 2;
          }

          message PhoneNumber {
          required string number = 1;
          optional PhoneType type = 2 [default = HOME];
          }

          repeated PhoneNumber phones = 4;
          }

          message AddressBook {
          repeated Person people = 1;
          }

          ☆☆☆注:

          • syntax = "proto2":指明版本
          • package:PB的自己的包名,防止不同 .proto 項(xiàng)目間命名 發(fā)生沖突
          • java_package:生成java類的包名,如不顯式指定,默認(rèn)包名為:按照應(yīng)用名稱倒序方式進(jìn)行排序
          • java_outer_classname:生成 java類的類名,如不顯式指定,則默認(rèn)為把.proto文件名轉(zhuǎn)換為首字母大寫來(lái)生成
          • message: 你的消息格式,各數(shù)據(jù)類型(boolint32floatdouble,  string ,enum ... )字段的集合,在一個(gè).proto文件中可以定義多個(gè)message,一個(gè)message里也可以定義另外一個(gè)message(相當(dāng)于java的類,當(dāng)然也可以有內(nèi)部類)
          • 當(dāng)然PB也是支持和java一樣的import的,import "xxx.proto";
          • 像每個(gè)字段也必須有修飾符,PB提供的字段修飾符有3種
            • required:必填
            • optional:可選
            • repeated :可重復(fù)字段,可放集合
          • 標(biāo)識(shí)號(hào):通過(guò)二進(jìn)制格式唯一標(biāo)識(shí)每個(gè)字段 ,使用后就不能夠再改變
            • 范圍 [1,15] 標(biāo)識(shí)號(hào)的字段 在編碼時(shí)占用1個(gè)字節(jié);
            • 范圍 [16,2047] 標(biāo)識(shí)號(hào)的字段 在編碼時(shí)占用2個(gè)字節(jié)
            • 為頻繁出現(xiàn)的 消息字段 保留 [1,15] 的標(biāo)識(shí)號(hào)
            • 標(biāo)識(shí)號(hào)使用范圍:[1,2的29次方 - 1]
            • 不可使用 [19000-19999] 標(biāo)識(shí)號(hào), 因?yàn)?Protobuf 協(xié)議實(shí)現(xiàn)中對(duì)這些標(biāo)識(shí)號(hào)進(jìn)行了預(yù)留。假若使用,則會(huì)報(bào)錯(cuò)
            • 每個(gè)字段在進(jìn)行編碼時(shí)都會(huì)占用內(nèi)存,而 占用內(nèi)存大小 取決于 標(biāo)識(shí)號(hào):
          54219a9749221a00def00e9ca9dc9252.webp
          2. 使用 protocol buffer 編譯器(下載地址:https://github.com/protocolbuffers/protobuf/releases )
          winows的話 cmd到編譯器安裝目錄的bin目錄中,執(zhí)行  protoc.exe -h  (E:\learning\protoc-3.9.0-win64\bin>protoc.exe -h),可以看到參數(shù)說(shuō)明。

          執(zhí)行:protoc -I=源地址 --java_out=目標(biāo)地址  源地址/xxx.proto

          E:\learning\protoc-3.9.0-win64\bin>protoc.exe -I=E:\learning\ --java_out=E:\learning\ E:\learning\addressbook.proto

          實(shí)際使用中:

          protoc.exe -I=E:\learn-workspace\starfish\starfish-learn\src\main\java\priv\starfish\ProtocolBuffers\proto\ --java_out=E:\learn-workspace\starfish\starfish-learn\src\main\java  E:\learn-workspace\starfish\starfish-learn\src\main\java\priv\starfish\ProtocolBuffers\proto\addressbook.proto)

          f12e7cb6e3555bc5b95e3d97c0ef5bba.webppd-idea-screenshot
          3. 通過(guò) Java protocol buffer API 讀寫消息格式
          package priv.starfish.ProtocolBuffers;
          import com.google.protobuf.InvalidProtocolBufferException;
          import priv.starfish.ProtocolBuffers.AddressBookProtos.Person;
          import priv.starfish.ProtocolBuffers.AddressBookProtos.AddressBook;
          import java.util.Arrays;
          /**
          * @author: starfish
          * @date: 2019/7/24 14:39
          * @description:
          */

          public class HelloProto {
          public static void main(String[] args) {
          Person person = Person.newBuilder()
          .setId(123)
          .setName("starfish")
          .setEmail("[email protected]")
          .addPhones(AddressBookProtos.Person.PhoneNumber.newBuilder()
          .setType(AddressBookProtos.Person.PhoneType.HOME)
          .setNumber("13555555555")
          .build())
          .build();

          System.out.println(person.toString());
          System.out.println(person.isInitialized());

          try {
          //序列化和反序列化
          System.out.println(Arrays.toString(person.toByteArray()));
          System.out.println(person.toByteString());
          Person newPerson = Person.parseFrom(person.toByteArray());
          System.out.println(newPerson);
          newPerson = Person.parseFrom(person.toByteString());
          System.out.println(newPerson);
          } catch (InvalidProtocolBufferException e) {
          e.printStackTrace();
          }

          // 向地址簿添加兩條Person信息
          AddressBook.Builder books = AddressBook.newBuilder();
          books.addPeople(person);
          books.addPeople(Person.newBuilder(person).setEmail("[email protected]")
          .build());
          System.out.println("AddressBook對(duì)象信息:");
          System.out.println(books.build());
          }
          }

          編譯后生成的java類是不可變的,類似java的String,不可修改

          構(gòu)造消息,必須先構(gòu)造一個(gè)builder,然后set屬性(可以一連串的set),最后調(diào)用build() 方法。

          PB常用方法

          • isInitialized(): 檢查必填字段(required)是否有set值

          • toString(): 返回message的可讀字符串格式

          • mergeFrom(Message other): 合并message

          • clear(): 清空字段值

          • byte[] toByteArray();: 序列化message,返回字節(jié)數(shù)組

          • MessageType parseFrom(byte[] data);: 解析給定的字節(jié)數(shù)組

          • void writeTo(OutputStream output);: 序列化message并寫入輸出流OutputStream.

          • MessageType parseFrom(InputStream input);: 從輸入流 InputStream讀取并解析message

          Reference:

          https://github.com/halfrost/Halfrost-Field/blob/master/contents/Protocol/Protocol-buffers-encode.md#六-protocol-buffer-編碼原理

          各類知識(shí)點(diǎn)總結(jié)

          下面的文章都有對(duì)應(yīng)的原創(chuàng)精美PDF,在持續(xù)更新中,可以來(lái)找我催更~

          掃碼或者微信搜Java3y 免費(fèi)領(lǐng)取原創(chuàng)思維導(dǎo)圖、精美PDF。在公眾號(hào)回復(fù)「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來(lái)問(wèn)我。


          
           

          原創(chuàng)電子書
          9801463fcf78af6ccc7479217b31b8e2.webp

          原創(chuàng)思維導(dǎo)圖

          a0d7251d16e22f5e0f0df7fe9eb43593.webp


          d689de1508a139a03adf81aa62001909.webp

          7dbd3cdbfcdadb463def1694d455323a.webp

          7dbd3cdbfcdadb463def1694d455323a.webp

          我是三歪,一個(gè)想要變強(qiáng)的男人,感謝大家的點(diǎn)贊收藏和轉(zhuǎn)發(fā),下期見。
          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美黄片视频播放 | 看片一区 | 四虎国产精品成人永久免费 | 免费看日韩无码AV中文字幕 | 国产成年女人性爱视频 |