Protobuf

Protobuf介紹

Protocol Buffers 是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式,被普遍應用在網絡傳輸java

Protobuf編碼原理

  • Message Buffer
    Message Buffer是指protobuf序列化後的二進制文件格式以下:

    如圖所示,消息通過序列化後會成爲一個二進制數據流,該流中的數據爲一系列的 Key-Value。protobuf採用Varint編碼、ZigZag編碼技術,使得這種Key-Pair 結構無需使用分隔符來分割不一樣的 Field。對於可選的 Field,若是消息中不存在該 field,那麼在最終的 Message Buffer 中就沒有該 field,這些特性都有助於節約消息自己的大小,protobuf利用巧妙的編碼技術,壓縮傳輸的字節數,可大大的提高網絡傳輸效率
  • Varint編碼數據庫

    • 原理介紹
      varint是一種對數字進行編碼的方案,編碼後的數據是不定長的,值越小的數字使用越小的字節數,編碼後的通常佔在1~5個字節。最高位表示是否繼續,繼續是1,表明後面7位仍然表示數字,不然爲0,後面7位用原碼補齊,小字節序
    • 小試牛刀
      400對應的二進制爲00000001 10010000(原碼)
    1. 每一個字節保留後7位,去掉最高位,有效編碼向前移動,生成編碼如:0000011 0010000
    2. 由於protobuf使用的是小字節序,因此要把低位字節寫到高字節,最後一個字節高位補0,其他各字節高位補1,生成編碼如:10010000 0000011
    • Varint編碼缺點 計算機在表示負數的時候,最高位是1,致使使用varint編碼的時候,會看成很大的整數處理,從而致使浪費資源,爲了解決該問題,protobuf編碼引入zigzag編碼
  • ZigZag編碼bash

    • 原理介紹
      Zigzag 編碼用無符號數來表示有符號數字,正數和負數交錯,如圖所示:

      使用 zigzag 編碼,絕對值小的數字,不管正負均可以採用較少的 byte 來表示,充分利用了 Varint 這種技術。在實際使用過程當中,先用zigzag編碼後,再對編碼後的數據進行varint編碼,能夠節省很大的空間
  • 字符串類型
    字符串等則採用相似數據庫中的 varchar 的表示方法,即用一個 varint 表示長度,而後將其他部分緊跟在這個長度部分以後便可網絡

  • key的計算方式maven

    • wireTypeui

    • 源碼展現google

    /** Makes a tag value given a field number and wire type. */
    static int makeTag(final int fieldNumber, final int wireType) {
        return (fieldNumber << TAG_TYPE_BITS) | wireType;
    }
    複製代碼

    TAG_TYPE_BITS取值爲3,也就是低位爲wire_type,高位爲field_number,舉例說明:age聲明爲int32,age的field_number=1,因此wire_type =0,因此key=(1<<3 | 0 )=0x08編碼

protobuf序列化

  • protobuf文件spa

    syntax ="proto3";
            package com.simple;
            option java_package="com.simple";
            option java_outer_classname="Person";
            message Person{
                int32 age= 1;
            }
    
    複製代碼
  • 序列化插件

    Person.Builder builder = Person.newBuilder();
    builder.setAge(18);
    Person person =builder.build();
    byte[] byteArray = person.toByteArray();
    FileOutputStream outstream = new FileOutputStream(new File("Person.txt"));
    outstream.write(byteArray);
    outstream.close();
    複製代碼

    打開Person.txt,使用十六進制查看:08 12

grpc應用

  • 概要

    protobuf提供了maven插件,能夠利用插件生成對應的文件,如Java,能夠生成對應的Java類,具體使用方法,這裏再也不累贅介紹

  • protobuf文件

    syntax = "proto3";
        option java_multiple_files = true;
        option java_package = "io.grpc.examples.helloworld";
        option java_outer_classname = "HelloWorldProto";
        option objc_class_prefix = "HLW";
    
        package helloworld;
    
        // The greeting service definition.
        service Greeter {
        // Sends a greeting
        rpc SayHello (HelloRequest) returns (HelloReply) {}
        }
    
        // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } 複製代碼
  • maven依賴

    <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.5.0</version>
        </dependency>
    複製代碼
  • maven配置protobuf插件

    <!-- protobuf 編譯組件 -->
        <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.5.1</version>
                <extensions>true</extensions>
                <configuration>
                    <pluginId>grpc-java</pluginId>
                    <protocArtifact>com.google.protobuf:protoc:3.5.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.16.1:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>${project.basedir}/src/main/resources/proto</protoSourceRoot>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
         </plugin>
    複製代碼

相關文章
相關標籤/搜索