欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

高效數(shù)據(jù)傳輸?shù)拿孛芪淦鱌rotobuf的使用教程

 更新時(shí)間:2023年05月11日 10:35:20   作者:程序猿阿朗  
Protobuf(Protocol?Buffers)是由?Google?開發(fā)的一種輕量級(jí)、高效的數(shù)據(jù)交換格式,它被用于結(jié)構(gòu)化數(shù)據(jù)的序列化、反序列化和傳輸,本文主要介紹了它的具體使用方法,需要的可以參考一下

當(dāng)涉及到網(wǎng)絡(luò)通信和數(shù)據(jù)存儲(chǔ)時(shí),數(shù)據(jù)序列化一直都是一個(gè)重要的話題;特別是現(xiàn)在很多公司都在推行微服務(wù),數(shù)據(jù)序列化更是重中之重,通常會(huì)選擇使用 JSON 作為數(shù)據(jù)交換格式,且 JSON 已經(jīng)成為業(yè)界的主流。但是 Google 這么大的公司使用的卻是一種被稱為 Protobuf 的數(shù)據(jù)交換格式,它是有什么優(yōu)勢(shì)嗎?這篇文章介紹 Protobuf 的相關(guān)知識(shí)。

GitHub:https://github.com/protocolbuffers/protobuf

官方文檔:https://protobuf.dev/overview/

Protobuf 介紹

Protobuf(Protocol Buffers)是由 Google 開發(fā)的一種輕量級(jí)、高效的數(shù)據(jù)交換格式,它被用于結(jié)構(gòu)化數(shù)據(jù)的序列化、反序列化和傳輸。相比于 XML 和 JSON 等文本格式,Protobuf 具有更小的數(shù)據(jù)體積、更快的解析速度和更強(qiáng)的可擴(kuò)展性。

Protobuf 的核心思想是使用協(xié)議(Protocol)來定義數(shù)據(jù)的結(jié)構(gòu)和編碼方式。使用 Protobuf,可以先定義數(shù)據(jù)的結(jié)構(gòu)和各字段的類型、字段等信息,然后使用Protobuf提供的編譯器生成對(duì)應(yīng)的代碼,用于序列化和反序列化數(shù)據(jù)。由于 Protobuf 是基于二進(jìn)制編碼的,因此可以在數(shù)據(jù)傳輸和存儲(chǔ)中實(shí)現(xiàn)更高效的數(shù)據(jù)交換,同時(shí)也可以跨語言使用。

相比于 XML 和 JSON,Protobuf 有以下幾個(gè)優(yōu)勢(shì)

  • 更小的數(shù)據(jù)量:Protobuf 的二進(jìn)制編碼通常比 XML 和 JSON 小 3-10 倍,因此在網(wǎng)絡(luò)傳輸和存儲(chǔ)數(shù)據(jù)時(shí)可以節(jié)省帶寬和存儲(chǔ)空間。
  • 更快的序列化和反序列化速度:由于 Protobuf 使用二進(jìn)制格式,所以序列化和反序列化速度比 XML 和 JSON 快得多。
  • 跨語言:Protobuf 支持多種編程語言,可以使用不同的編程語言來編寫客戶端和服務(wù)端。這種跨語言的特性使得 Protobuf 受到很多開發(fā)者的歡迎(JSON 也是如此)。
  • 易于維護(hù)可擴(kuò)展:Protobuf 使用 .proto 文件定義數(shù)據(jù)模型和數(shù)據(jù)格式,這種文件比 XML 和 JSON 更容易閱讀和維護(hù),且可以在不破壞原有協(xié)議的基礎(chǔ)上,輕松添加或刪除字段,實(shí)現(xiàn)版本升級(jí)和兼容性。

編寫 Protobuf

使用 Protobuf 的語言定義文件(.proto)可以定義要傳輸?shù)男畔⒌臄?shù)據(jù)結(jié)構(gòu),可以包括各個(gè)字段的名稱、類型等信息。同時(shí)也可以相互嵌套組合,構(gòu)造出更加復(fù)雜的消息結(jié)構(gòu)。

比如想要構(gòu)造一個(gè)地址簿 AddressBook 信息結(jié)構(gòu)。一個(gè) AddressBook 可以包含多個(gè)人員 Person 信息,每個(gè) Person 信息可以包含 id、name、email 信息,同時(shí)一個(gè) Person 也可以包含多個(gè)電話號(hào)碼信息 PhoneNumber,每個(gè)電話號(hào)碼信息需要指定號(hào)碼種類,如手機(jī)、家庭電話、工作電話等。

如果使用 Protobuf 編寫定義文件如下:

// 文件:addressbook.proto
syntax = "proto3";
// 指定 protobuf 包名,防止有相同類名的 message 定義
package com.wdbyte.protobuf;
// 是否生成多個(gè)文件
option java_multiple_files = true;
// 生成的文件存放在哪個(gè)包下
option java_package = "com.wdbyte.tool.protos";
// 生成的類名,如果沒有指定,會(huì)根據(jù)文件名自動(dòng)轉(zhuǎn)駝峰來命名
option java_outer_classname = "AddressBookProtos";

message Person {
  // =1,=2 作為序列化后的二進(jìn)制編碼中的字段的唯一標(biāo)簽,也因此,1-15 比 16 會(huì)少一個(gè)字節(jié),所以盡量使用 1-15 來指定常用字段。
  optional int32 id = 1;
  optional string name = 2;
  optional string email = 3;

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

  message PhoneNumber {
    optional string number = 1;
    optional PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

Protobuf 文件中的語法解釋。

頭部全局定義

  • syntax = "proto3";指定 Protobuf 版本為版本3(最新版本)
  • package com.wdbyte.protobuf;指定 Protobuf 包名,防止有相同類名的 message 定義,這個(gè)包名是生成的類中所用到的一些信息的前綴,并非類所在包。
  • option java_multiple_files = true; 是否生成多個(gè)文件。若 false,則只會(huì)生成一個(gè)類,其他類以內(nèi)部類形式提供。
  • option java_package = 生成的類所在包。
  • option java_outer_classname 生成的類名,若無,自動(dòng)使用文件名進(jìn)行駝峰轉(zhuǎn)換來為類命名。

消息結(jié)構(gòu)具體定義

message Person 定一個(gè)了一個(gè) Person 類。

Person 類中的字段被 optional 修飾,被 optional 修飾說明字段可以不賦值。

  • 修飾符 optional 表示可選字段,可以不賦值。
  • 修飾符 repeated 表示數(shù)據(jù)重復(fù)多個(gè),如數(shù)組,如 List。
  • 修飾符 required 表示必要字段,必須給值,否則會(huì)報(bào)錯(cuò) RuntimeException,但是在 Protobuf 版本 3 中被移除。即使在版本 2 中也應(yīng)該慎用,因?yàn)橐坏┒x,很難更改。

字段類型定義

修飾符后面緊跟的是字段類型,如 int32 、string。常用的類型如下:

  • int32、int64、uint32、uint64:整數(shù)類型,包括有符號(hào)和無符號(hào)類型。
  • float、double:浮點(diǎn)數(shù)類型。
  • bool:布爾類型,只有兩個(gè)值,true 和 false。
  • string:字符串類型。
  • bytes:二進(jìn)制數(shù)據(jù)類型。
  • enum:枚舉類型,枚舉值可以是整數(shù)或字符串。
  • message:消息類型,可以嵌套其他消息類型,類似于結(jié)構(gòu)體。

字段后面的 =1,=2 是作為序列化后的二進(jìn)制編碼中的字段的對(duì)應(yīng)標(biāo)簽,因?yàn)?Protobuf 消息在序列化后是不包含字段信息的,只有對(duì)應(yīng)的字段序號(hào),所以節(jié)省了空間。也因此,1-15 比 16 會(huì)少一個(gè)字節(jié),所以盡量使用 1-15 來指定常用字段。且一旦定義,不要隨意更改,否則可能會(huì)對(duì)不上序列化信息。

編譯 Protobuf

使用 Protobuf 提供的編譯器,可以將 .proto 文件編譯成各種語言的代碼文件(如 Java、C++、Python 等)。

下載編譯器:https://github.com/protocolbuffers/protobuf/releases/latest

安裝完成后可以使用 protoc 命令編譯 proto 文件,如編譯示例中的 addressbook.proto.

protoc --java_out=./java ./resources/addressbook.proto
# --java_out 指定輸出 java 格式文件,輸出到 ./java 目錄
# ./resources/addressbook.proto 為 proto 文件位置

生成后可以看到生產(chǎn)的類文件。

./
├── java
│   └── com
│       └── wdbyte
│           └── tool
│               ├── protos
│               │   ├── AddressBook.java
│               │   ├── AddressBookOrBuilder.java
│               │   ├── AddressBookProtos.java
│               │   ├── Person.java
│               │   ├── PersonOrBuilder.java
└── resources
    ├── addressbook.proto
 

使用 Protobuf

使用 Java 語言操作 Protobuf,首先需要引入 Protobuf 依賴。

Maven 依賴:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.22.3</version>
</dependency>

構(gòu)造消息對(duì)象

// 直接構(gòu)建
PhoneNumber phoneNumber1 = PhoneNumber.newBuilder().setNumber("18388888888").setType(PhoneType.HOME).build();
Person person1 = Person.newBuilder().setId(1).setName("www.wdbyte.com").setEmail("xxx@wdbyte.com").addPhones(phoneNumber1).build();
AddressBook addressBook1 = AddressBook.newBuilder().addPeople(person1).build();
System.out.println(addressBook1);
System.out.println("------------------");

//  鏈?zhǔn)綐?gòu)建
AddressBook addressBook2 = AddressBook
    .newBuilder()
    .addPeople(Person.newBuilder()
                     .setId(2)
                     .setName("www.wdbyte.com")
                     .setEmail("yyy@126.com")
                    .addPhones(PhoneNumber.newBuilder()
                                          .setNumber("18388888888")
                                          .setType(PhoneType.HOME)
                    )
    )
    .build();
System.out.println(addressBook2);

輸出:

people {
  id: 1
  name: "www.wdbyte.com"
  email: "xxx@wdbyte.com"
  phones {
    number: "18388888888"
    type: HOME
  }
}

------------------
people {
  id: 2
  name: "www.wdbyte.com"
  email: "yyy@126.com"
  phones {
    number: "18388888888"
    type: HOME
  }
}

序列化、反序列化

序列化:將內(nèi)存中的數(shù)據(jù)對(duì)象序列化為二進(jìn)制數(shù)據(jù),可以用于網(wǎng)絡(luò)傳輸或存儲(chǔ)等場(chǎng)景。

反序列化:將二進(jìn)制數(shù)據(jù)反序列化成內(nèi)存中的數(shù)據(jù)對(duì)象,可以用于數(shù)據(jù)處理和業(yè)務(wù)邏輯。

下面演示使用 Protobuf 進(jìn)行字符數(shù)組和文件的序列化及反序列化過程。

package com.wdbyte.tool.protos;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 
 * @author www.wdbyte.com
 */
public class ProtobufTest2 {

    public static void main(String[] args) throws IOException {
        PhoneNumber phoneNumber1 = PhoneNumber.newBuilder().setNumber("18388888888").setType(PhoneType.HOME).build();
        Person person1 = Person.newBuilder().setId(1).setName("www.wdbyte.com").setEmail("xxx@wdbyte.com").addPhones(phoneNumber1).build();
        AddressBook addressBook1 = AddressBook.newBuilder().addPeople(person1).build();
      
        // 序列化成字節(jié)數(shù)組
        byte[] byteArray = addressBook1.toByteArray();
        // 反序列化 - 字節(jié)數(shù)組轉(zhuǎn)對(duì)象
        AddressBook addressBook2 = AddressBook.parseFrom(byteArray);
        System.out.println("字節(jié)數(shù)組反序列化:");
        System.out.println(addressBook2);

        // 序列化到文件
        addressBook1.writeTo(new FileOutputStream("AddressBook1.txt"));
        // 讀取文件反序列化
        AddressBook addressBook3 = AddressBook.parseFrom(new FileInputStream("AddressBook1.txt"));
        System.out.println("文件讀取反序列化:");
        System.out.println(addressBook3);
    }
}

輸出:

字節(jié)數(shù)組反序列化:
people {
  id: 1
  name: "www.wdbyte.com"
  email: "xxx@wdbyte.com"
  phones {
    number: "18388888888"
    type: HOME
  }
}

文件讀取反序列化:
people {
  id: 1
  name: "www.wdbyte.com"
  email: "xxx@wdbyte.com"
  phones {
    number: "18388888888"
    type: HOME
  }
}

Protobuf 為什么高效

在分析 Protobuf 高效之前,我們先確認(rèn)一下 Protobuf 是否真的高效,下面將 Protobuf 與 JSON 進(jìn)行對(duì)比,分別對(duì)比序列化和反序列化速度以及序列化后的存儲(chǔ)占用大小。

測(cè)試工具:JMH,F(xiàn)astJSON,

測(cè)試對(duì)象:Protobuf 的 addressbook.proto,JSON 的普通 Java 類。

Maven 依賴:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.7</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.33</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.33</version>
    <scope>provided</scope>
</dependency>

先編寫與addressbook.proto 結(jié)構(gòu)相同的 Java 類 AddressBookJava.java.

public class AddressBookJava {
    List&lt;PersonJava&gt; personJavaList;

    public static class PersonJava {
        private int id;
        private String name;
        private String email;
        private PhoneNumberJava phones;
        // get...set...
    }

    public static class PhoneNumberJava {
        private String number;
        private PhoneTypeJava phoneTypeJava;
        // get....set....
    }

    public enum PhoneTypeJava {
        MOBILE, HOME, WORK;
    }

    public List&lt;PersonJava&gt; getPersonJavaList() {
        return personJavaList;
    }

    public void setPersonJavaList(List&lt;PersonJava&gt; personJavaList) {
        this.personJavaList = personJavaList;
    }
}

序列化大小對(duì)比

分別在地址簿中添加 1000 個(gè)人員信息,輸出序列化后的數(shù)組大小。

package com.wdbyte.tool.protos;

import java.io.IOException;
import java.util.ArrayList;

import com.alibaba.fastjson.JSON;

import com.wdbyte.tool.protos.AddressBook.Builder;
import com.wdbyte.tool.protos.AddressBookJava.PersonJava;
import com.wdbyte.tool.protos.AddressBookJava.PhoneNumberJava;
import com.wdbyte.tool.protos.AddressBookJava.PhoneTypeJava;
import com.wdbyte.tool.protos.Person.PhoneNumber;
import com.wdbyte.tool.protos.Person.PhoneType;

/**
 * @author https://www.wdbyte.com
 */
public class ProtobufTest3 {

    public static void main(String[] args) throws IOException {
        AddressBookJava addressBookJava = createAddressBookJava(1000);
        String jsonString = JSON.toJSONString(addressBookJava);
        System.out.println("json string size:" + jsonString.length());

        AddressBook addressBook = createAddressBook(1000);
        byte[] addressBookByteArray = addressBook.toByteArray();
        System.out.println("protobuf byte array size:" + addressBookByteArray.length);
    }

    public static AddressBook createAddressBook(int personCount) {
        Builder builder = AddressBook.newBuilder();
        for (int i = 0; i &lt; personCount; i++) {
            builder.addPeople(Person.newBuilder()
                .setId(i)
                .setName("www.wdbyte.com")
                .setEmail("xxx@126.com")
                .addPhones(PhoneNumber.newBuilder()
                    .setNumber("18333333333")
                    .setType(PhoneType.HOME)
                )
            );
        }
        return builder.build();
    }

    public static AddressBookJava createAddressBookJava(int personCount) {
        AddressBookJava addressBookJava = new AddressBookJava();
        addressBookJava.setPersonJavaList(new ArrayList&lt;&gt;());
        for (int i = 0; i &lt; personCount; i++) {
            PersonJava personJava = new PersonJava();
            personJava.setId(i);
            personJava.setName("www.wdbyte.com");
            personJava.setEmail("xxx@126.com");

            PhoneNumberJava numberJava = new PhoneNumberJava();
            numberJava.setNumber("18333333333");
            numberJava.setPhoneTypeJava(PhoneTypeJava.HOME);

            personJava.setPhones(numberJava);
            addressBookJava.getPersonJavaList().add(personJava);
        }
        return addressBookJava;
    }
}

輸出:

json string size:108910
protobuf byte array size:50872

可見測(cè)試中 Protobuf 的序列化結(jié)果比 JSON 小了將近一倍左右。

序列化速度對(duì)比

使用 JMH 進(jìn)行性能測(cè)試,分別測(cè)試 JSON 的序列化和反序列以及 Protobuf 的序列化和反序列化性能情況。每次測(cè)試前進(jìn)行 3 次預(yù)熱,每次 3 秒。接著進(jìn)行 5 次測(cè)試,每次 3 秒,收集測(cè)試情況。

package com.wdbyte.tool.protos;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;

import com.google.protobuf.InvalidProtocolBufferException;
import com.wdbyte.tool.protos.AddressBook.Builder;
import com.wdbyte.tool.protos.AddressBookJava.PersonJava;
import com.wdbyte.tool.protos.AddressBookJava.PhoneNumberJava;
import com.wdbyte.tool.protos.AddressBookJava.PhoneTypeJava;
import com.wdbyte.tool.protos.Person.PhoneNumber;
import com.wdbyte.tool.protos.Person.PhoneType;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

/**
 * @author https://www.wdbyte.com
 */
@State(Scope.Thread)
@Fork(2)
@Warmup(iterations = 3, time = 3)
@Measurement(iterations = 5, time = 3)
@BenchmarkMode(Mode.Throughput) // Throughput:吞吐量,SampleTime:采樣時(shí)間
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class ProtobufTest4 {

    private AddressBookJava addressBookJava;
    private AddressBook addressBook;

    @Setup
    public void init() {
        addressBookJava = createAddressBookJava(1000);
        addressBook = createAddressBook(1000);
    }

    @Benchmark
    public AddressBookJava testJSON() {
        // 轉(zhuǎn) JSON
        String jsonString = JSON.toJSONString(addressBookJava);
        // JSON 轉(zhuǎn)對(duì)象
        return JSON.parseObject(jsonString, AddressBookJava.class);
    }

    @Benchmark
    public AddressBook testProtobuf() throws InvalidProtocolBufferException {
        // 轉(zhuǎn) JSON
        byte[] addressBookByteArray = addressBook.toByteArray();
        // JSON 轉(zhuǎn)對(duì)象
        return AddressBook.parseFrom(addressBookByteArray);
    }

    public static AddressBook createAddressBook(int personCount) {
        Builder builder = AddressBook.newBuilder();
        for (int i = 0; i &lt; personCount; i++) {
            builder.addPeople(Person.newBuilder()
                .setId(i)
                .setName("www.wdbyte.com")
                .setEmail("xxx@126.com")
                .addPhones(PhoneNumber.newBuilder()
                    .setNumber("18333333333")
                    .setType(PhoneType.HOME)
                )
            );
        }
        return builder.build();
    }

    public static AddressBookJava createAddressBookJava(int personCount) {
        AddressBookJava addressBookJava = new AddressBookJava();
        addressBookJava.setPersonJavaList(new ArrayList&lt;&gt;());
        for (int i = 0; i &lt; personCount; i++) {
            PersonJava personJava = new PersonJava();
            personJava.setId(i);
            personJava.setName("www.wdbyte.com");
            personJava.setEmail("xxx@126.com");

            PhoneNumberJava numberJava = new PhoneNumberJava();
            numberJava.setNumber("18333333333");
            numberJava.setPhoneTypeJava(PhoneTypeJava.HOME);

            personJava.setPhones(numberJava);
            addressBookJava.getPersonJavaList().add(personJava);
        }
        return addressBookJava;
    }
}

JMH 吞吐量測(cè)試結(jié)果(Score 值越大吞吐量越高,性能越好):

Benchmark                    Mode  Cnt  Score   Error   Units
ProtobufTest3.testJSON      thrpt   10  1.877 ± 0.287  ops/ms
ProtobufTest3.testProtobuf  thrpt   10  2.813 ± 0.446  ops/ms

JMH 采樣時(shí)間測(cè)試結(jié)果(Score 越小,采樣時(shí)間越小,性能越好):

Benchmark                                          Mode    Cnt   Score   Error  Units
ProtobufTest3.testJSON                           sample  53028   0.565 ± 0.005  ms/op
ProtobufTest3.testProtobuf                       sample  90413   0.332 ± 0.001  ms/op

從測(cè)試結(jié)果看,不管是吞吐量測(cè)試,還是采樣時(shí)間測(cè)試,Protobuf 都優(yōu)于 JSON。

為什么高效?

Protobuf 是如何實(shí)現(xiàn)這種高效緊湊的數(shù)據(jù)編碼和解碼的呢?

首先,Protobuf 使用二進(jìn)制編碼,會(huì)提高性能;其次 Protobuf 在將數(shù)據(jù)轉(zhuǎn)換成二進(jìn)制時(shí),會(huì)對(duì)字段和類型重新編碼,減少空間占用。它采用 TLV 格式來存儲(chǔ)編碼后的數(shù)據(jù)。TLV 也是就是 Tag-Length-Value ,是一種常見的編碼方式,因?yàn)閿?shù)據(jù)其實(shí)都是鍵值對(duì)形式,所以在 TAG 中會(huì)存儲(chǔ)對(duì)應(yīng)的字段和類型信息,Length 存儲(chǔ)內(nèi)容的長(zhǎng)度,Value 存儲(chǔ)具體的內(nèi)容。

還記得上面定義結(jié)構(gòu)體時(shí)每個(gè)字段都對(duì)應(yīng)一個(gè)數(shù)字嗎?如 =1,=2,=3.

message Person {
  optional int32 id = 1;
  optional string name = 2;
  optional string email = 3;
}

在序列化成二進(jìn)制時(shí)候就是通過這個(gè)數(shù)字來標(biāo)記對(duì)應(yīng)的字段的,二進(jìn)制中只存儲(chǔ)這個(gè)數(shù)字,反序列化時(shí)通過這個(gè)數(shù)字找對(duì)應(yīng)的字段。這也是上面為什么說盡量使用 1-15 范圍內(nèi)的數(shù)字,因?yàn)橐坏┏^ 15,就需要多一個(gè) bit 位來存儲(chǔ)。

那么類型信息呢?比如 int32 怎么標(biāo)記,因?yàn)轭愋蛡€(gè)數(shù)有限,所以 Protobuf 規(guī)定了每個(gè)類型對(duì)應(yīng)的二進(jìn)制編碼,比如 int32 對(duì)應(yīng)二進(jìn)制 000,string 對(duì)應(yīng)二進(jìn)制 010,這樣就可以只用三個(gè)比特位存儲(chǔ)類型信息。

這里只是舉例描述大概思想,具體還有一些變化。

詳情可以參考官方文檔:https://protobuf.dev/programming-guides/encoding/

其次,Protobuf 還會(huì)采用一種變長(zhǎng)編碼的方式來存儲(chǔ)數(shù)據(jù)。這種編碼方式能夠保證數(shù)據(jù)占用的空間最小化,從而減少了數(shù)據(jù)傳輸和存儲(chǔ)的開銷。具體來說,Protobuf 會(huì)將整數(shù)和浮點(diǎn)數(shù)等類型變換成一個(gè)或多個(gè)字節(jié)的形式,其中每個(gè)字節(jié)都包含了一部分?jǐn)?shù)據(jù)信息和一部分標(biāo)識(shí)符信息。這種編碼方式可以在數(shù)據(jù)值比較小的情況下,只使用一個(gè)字節(jié)來存儲(chǔ)數(shù)據(jù),以此來提高編碼效率。

最后,Protobuf 還可以通過采用壓縮算法來減少數(shù)據(jù)傳輸?shù)拇笮?/strong>。比如 GZIP 算法能夠?qū)⒃紨?shù)據(jù)壓縮成更小的二進(jìn)制格式,從而在網(wǎng)絡(luò)傳輸中能夠節(jié)省帶寬和傳輸時(shí)間。Protobuf 還提供了一些可選的壓縮算法,如 zlib 和 snappy,這些算法在不同的場(chǎng)景下能夠適應(yīng)不同的壓縮需求。

綜上所述,Protobuf 在實(shí)現(xiàn)高效編碼和解碼的過程中,采用了多種優(yōu)化方式,從而在實(shí)際應(yīng)用中能夠有效地提升數(shù)據(jù)傳輸和處理的效率。

總結(jié)

ProtoBuf 是一種輕量、高效的數(shù)據(jù)交換格式,它具有以下優(yōu)點(diǎn):

  • 語言中立,可以支持多種編程語言;
  • 數(shù)據(jù)結(jié)構(gòu)清晰,易于維護(hù)和擴(kuò)展;
  • 二進(jìn)制編碼,數(shù)據(jù)體積小,傳輸效率高;
  • 自動(dòng)生成代碼,開發(fā)效率高。

但是,ProtoBuf 也存在以下缺點(diǎn):

  • 學(xué)習(xí)成本較高,需要掌握其語法規(guī)則和使用方法;
  • 需要先定義數(shù)據(jù)結(jié)構(gòu),然后才能對(duì)數(shù)據(jù)進(jìn)行序列化和反序列化,增加了一定的開發(fā)成本;
  • 由于二進(jìn)制編碼,可讀性較差,這點(diǎn)不如 JSON 可以直接閱讀。

總體來說,Protobuf 適合用于數(shù)據(jù)傳輸和存儲(chǔ)等場(chǎng)景,能夠提高數(shù)據(jù)傳輸效率和減少數(shù)據(jù)體積。但對(duì)于需要人類可讀的數(shù)據(jù),或需要實(shí)時(shí)修改的數(shù)據(jù),或者對(duì)數(shù)據(jù)的傳輸效率和體積沒那么在意的場(chǎng)景,選擇更加通用的 JSON 未嘗不是一個(gè)好的選擇。

以上就是高效數(shù)據(jù)傳輸?shù)拿孛芪淦鱌rotobuf的使用教程的詳細(xì)內(nèi)容,更多關(guān)于Protobuf數(shù)據(jù)傳輸?shù)馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringCloud Nacos配置中心管理超詳細(xì)講解

    SpringCloud Nacos配置中心管理超詳細(xì)講解

    這篇文章主要介紹了Springcloud中的Nacos服務(wù)配置,本文以用戶微服務(wù)為例,進(jìn)行統(tǒng)一的配置,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • SpringBoot多配置切換的配置方法

    SpringBoot多配置切換的配置方法

    這篇文章主要介紹了SpringBoot多配置切換的配置方法及spring boot設(shè)置端口和上下文路徑的方法,需要的朋友可以參考下
    2018-04-04
  • SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能

    SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能

    WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動(dòng)發(fā)送信息給客戶端,本文給大家介紹了SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能,需要的朋友可以參考下
    2024-05-05
  • SpringMVC請(qǐng)求/響應(yīng)亂碼問題解決方案解析

    SpringMVC請(qǐng)求/響應(yīng)亂碼問題解決方案解析

    這篇文章主要介紹了SpringMVC請(qǐng)求/響應(yīng)亂碼問題解決方案解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • JAVA核心知識(shí)之ConcurrentHashMap源碼分析

    JAVA核心知識(shí)之ConcurrentHashMap源碼分析

    這篇文章主要介紹了JAVA核心知識(shí)之ConcurrentHashMap源碼分析,想了解ConcurrentHashMap的同學(xué)一定要看啊
    2021-04-04
  • springmvc數(shù)據(jù)的封裝過程詳解

    springmvc數(shù)據(jù)的封裝過程詳解

    這篇文章主要介紹了springmvc數(shù)據(jù)的封裝過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 解決RestTemplate 請(qǐng)求接收自定義400+ 或500+錯(cuò)誤

    解決RestTemplate 請(qǐng)求接收自定義400+ 或500+錯(cuò)誤

    這篇文章主要介紹了解決RestTemplate 請(qǐng)求接收自定義400+ 或500+錯(cuò)誤,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • apache commons工具集代碼詳解

    apache commons工具集代碼詳解

    這篇文章主要介紹了apache commons工具集代碼詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • Java超詳細(xì)講解多線程中的Process與Thread

    Java超詳細(xì)講解多線程中的Process與Thread

    進(jìn)程process:在一定的環(huán)境下,把靜態(tài)的程序代碼運(yùn)行起來,通過使用不同的資源,來完成一定的任務(wù);線程thread:是程序中一個(gè)單一的順序控制流程。在單個(gè)進(jìn)程中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱為多線程
    2022-05-05
  • Intellij IDEA集成JProfiler性能分析工具

    Intellij IDEA集成JProfiler性能分析工具

    作為Java程序員,性能分析是我們必須掌握的技能之一,在性能分析中,JProfiler是一款非常強(qiáng)大的工具,本文就來介紹一下Intellij IDEA集成JProfiler性能分析工具,就有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12

最新評(píng)論