`

(转)为什么Protobuf 的默认序列化格式没有包含消息的长度与类型

阅读更多

Protobuf 是经过深思熟虑的消息打包方案,它的默认序列化格式没有包含消息的长度与类型,自然有其道理。哪些情况下不需要在 protobuf 序列化得到的字节流中包含消息的长度和(或)类型?我能想到的答案有:

  • 如果把消息写入文件,一个文件存一个消息,那么序列化结果中不需要包含长度和类型,因为从文件名和文件长度中可以得知消息的类型与长度。
  • 如果把消息写入文件,一个文件存多个消息,那么序列化结果中不需要包含类型,因为文件名就代表了消息的类型。
  • 如果把消息存入数据库(或者 NoSQL),以 VARBINARY 字段保存,那么序列化结果中不需要包含长度和类型,因为从字段名和字段长度中可以得知消息的类型与长度。
  • 如果把消息以 UDP 方式发生给对方,而且对方一个 UDP port 只接收一种消息类型,那么序列化结果中不需要包含长度和类型,因为从 port 和 UDP packet 长度中可以得知消息的类型与长度。
  • 如果把消息以 TCP 短连接方式发给对方,而且对方一个 TCP port 只接收一种消息类型,那么序列化结果中不需要包含长度和类型,因为从 port 和 TCP 字节流长度中可以得知消息的类型与长度。
  • 如果把消息以 TCP 长连接方式发给对方,但是对方一个 TCP port 只接收一种消息类型,那么序列化结果中不需要包含类型,因为 port 代表了消息的类型。
  • 如果采用 RPC 方式通信,那么只需要告诉对方 method name,对方自然能推断出 Request 和 Response 的消息类型,这些可以由 protoc 生成的 RPC stubs 自动搞定。

对于最后一点,比方说 sudoku.proto 定义为:

service SudokuService {
  rpc Solve (SudokuRequest) returns (SudokuResponse);
}

那么 RPC method Sudoku.Solve 对应的请求和响应分别是 SudokuRequest 和 SudokuResponse。在发送 RPC 请求的时候,不需要包含 SudokuRequest 的类型,只需要发送 method name Sudoku.Solve,对方自知道应该按照 SudokuRequest 来解析(parse)请求。这个例子来自我的半成品项目 evproto,见 http://blog.csdn.net/Solstice/archive/2010/04/17/5497699.aspx 

对于上述这些情况,如果 protobuf 无条件地把长度和类型放到序列化的字节串中,只会浪费网络带宽和存储。可见 protobuf 默认不发送长度和类型是正确的决定。Protobuf 为消息格式的设计树立了典范,哪些该自己搞定,哪些留给外部系统去解决,这些都考虑得很清楚。

只有在使用 TCP 长连接,且在一个连接上传递不止一种消息的情况下(比方同时发 Heartbeat 和 Request/Response),才需要我前文提到的那种打包方案。(为什么要在一个连接上同时发 Heartbeat 和业务消息?请见陈硕《分布式系统的工程化开发方法》 p.51 心跳协议的设计。)这时候我们需要一个分发器 dispatcher,把不同类型的消息分给各个消息处理函数,这正是本文的主题之一。

分享到:
评论

相关推荐

    protobuf序列化和反序列化技术

    开发者应该熟悉protobuf的语法规则,掌握如何定义消息类型,以及如何在不同编程语言中使用生成的代码进行序列化和反序列化操作。对于大型团队,规范化的protobuf定义管理和版本控制也是必不可少的,以确保不同模块...

    protobuf常用序列化和反序列化API

    protobuf的核心在于定义消息类型(.proto文件),然后生成对应的编程语言代码,用于序列化和反序列化数据。 ### 1. 序列化 序列化是将结构化的数据转换为二进制流的过程,便于在网络中传输或持久化存储。在...

    Unity 中使用Protobuf进行序列化和反序列化的Demo

    在这个例子中,我们定义了一个`Player`消息类型,包含姓名、等级和分数字段。 然后,使用protobuf-net的工具(如`protogen.exe`)将.proto文件编译为C#类。这个编译后的类可以被Unity中的脚本直接使用。 在Unity...

    protobuf 序列化工具类

    本文将深入探讨protobuf的工作原理、使用方法、序列化与反序列化过程,以及如何使用protobuf工具类。 1. **protobuf工作原理** protobuf通过定义.proto文件来描述数据结构,这些文件包含了消息类型、字段、字段...

    自己实现的protobuf 压缩类,并能序列化反序列化

    在压缩包子文件的文件名称列表中,“协议文档.pdf”可能包含了protobuf的官方协议规范或者作者自定义的数据协议描述,用于指导如何定义和使用protobuf消息类型。“简介.txt”可能是对protobuf或者作者实现的压缩类的...

    在Unity5中Protobuf的序列化和反序列化

    这些类库包含了序列化和反序列化的函数,使得Unity中的C#对象可以轻松转换为二进制数据。 3. **Protobuf反序列化** 反序列化则是将二进制数据还原为对象的过程。在Unity5中,通过调用已生成的类库中的方法,我们...

    Google Protobuf基于Qt开发序列化与反序列化用QUdpSocket传输并显示。实例。

    Google Protobuf基于Qt开发序列化与反序列化用QUdpSocket传输并显示。实例。 具体可查看了解:https://blog.csdn.net/automoblie0/article/details/101363526

    java序列化之protobuf

    与Java默认的序列化机制相比,protobuf有几个显著优点: 1. 性能:protobuf序列化和反序列化速度比Java序列化快很多。 2. 数据大小:protobuf编码的数据通常比JSON或XML更小,节省了存储和网络传输成本。 3. 版本...

    ProtoBuf的介绍以及在Java中使用protobuf将对象进行序列化与反序列化示例代码.rar

    这个文件定义了一个名为Person的消息类型,包含name、id和email三个字段。 2. **生成Java代码** 使用protobuf编译器(protoc)将.proto文件转换为Java代码: ``` protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_...

    C#中使用二进制和ProtoBuf分别进行序列化、反序列化、压缩、解压缩对比测试示例源码.zip

    C#中的`System.Runtime.Serialization.Formatters.Binary.BinaryFormatter`类提供了一种默认的序列化方式,它将对象的状态转换为字节流。这种序列化方式简单易用,但生成的序列化数据通常较大,且不便于跨平台传输。...

    netty protobuf序列化 推送 android客户端

    总结来说,这个示例通过结合Netty的网络通信能力与protobuf的高效序列化机制,展示了如何在服务端和Android客户端之间安全地推送和接收结构化数据。这不仅提高了通信效率,也降低了开发复杂度,有利于构建稳定、高...

    protobuf序列化工具 v.1.1

    这次更新可能意味着工具现在完全兼容proto3的数组处理规范,使得用户在处理包含数组的protobuf消息时,能够享受到更高效、更节省空间的序列化和反序列化过程。 在SanYe标签下,我们可以推测这个工具可能是由一位名...

    C#中使用ProtoBuf提高序列化速度示例源码.zip

    protocolbuffer是google 的一种数据交换的格式,它独立于语言,独立于平台。 google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。

    Hive 对 Protobuf 序列化文件读取.zip

    Hive原生支持的序列化/反序列化方式(SerDe)主要是Text SerDe和Writable SerDe,但它们并不直接处理Protobuf格式的数据。为了在Hive中读取Protobuf序列化的文件,我们需要使用自定义的Protobuf SerDe,如本压缩包中...

    C# Protobuf-Net 序列化 样例

    Protocol Buffers是一种灵活、高效的结构化数据序列化机制,适用于各种平台和语言,包括C#。在C#中,Protobuf-Net提供了简单易用的API,使得开发者可以方便地将对象序列化为二进制格式,以便于存储或网络传输。 ...

    Python调用序列化数据工具Protocol Buffers——protobuf

    2. **编译器**: 使用protobuf编译器将`.proto`文件转换为特定语言(如Python、Java、C++)的源代码,生成的数据结构包含序列化和反序列化的方法。 3. **序列化与反序列化**: 序列化是将结构化数据转换为二进制流的...

    protobuf序列化JAVA使用的JAR包V3.15

    这些生成的类包含了序列化和反序列化的API,使得开发者可以轻松地在Java对象和protobuf二进制格式之间转换。 在编码阶段,可以通过protobuf的API创建、填充和读取protobuf消息。例如: ```java Person person = ...

    序列化工具(Gson, Jackson, FastJson, ProtoBuf)

    在IT领域,序列化是将对象的状态转换为可存储或传输的形式的过程,而反序列化则是将这种形式恢复为原始对象。在这个主题中,我们将深入探讨四种常用的序列化工具:Gson, Jackson, FastJson和ProtoBuf,以及与...

    ros2转protobuf,再转dds发出.

    2. **ROS2接口与protobuf集成**:在ROS2中,消息类型通常使用`msg`或`srv`定义,但你也可以使用protobuf定义消息类型。这需要将protobuf消息与ROS2的消息接口结合,通过编写适配器来转换数据格式。 3. **dds::topic...

Global site tag (gtag.js) - Google Analytics