消息中间件(序列化-反序列化)

发布时间:2025-12-09 16:24:13 浏览次数:3

Protobuf

[x]GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

是一种序列化与结构化数据的一种机制,具有跨平台、解析速度快、序列化数据体积小、扩展性高、使用简单的特点。

优点

  • 二进制消息,性能好/效率高(空间和时间效率都很不错)

  • proto文件生成目标代码,简单易用

  • 序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)

  • 支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级

  • 支持多种语言(可以把proto文件看做IDL文件)

  • Netty等一些框架集成

缺点

  • 官方只支持C++,JAVA和Python语言绑定

  • 二进制可读性差(貌似提供了Text_Fromat功能)

  • 二进制不具有自描述特性

  • 默认不具备动态特性(可以通过动态定义生成消息类型或者动态编译支持)

  • 只涉及序列化和反序列化技术,不涉及RPC功能(类似XML或者JSON的解析器)

Thrift

由Facebook开源的一个RPC框架,用来进行可扩展且跨语言的服务的开发,使得各种编程语言间无缝结合的、高效的服务。我们依据Thrift的规范 简单定义访问接口,通过Thrift编译器编译生成各种编程语言代码,实现各种语言模块之间的高效互访问,速度比Google的Protocol Buffers还要快。Thrift可以说它是现在最优秀的分布式通信机制,实现了在大型分布式集群中各独立模块之间的高效协同。

应用

  • Facebook的开源的日志收集系统(scribe: GitHub - facebookarchive/scribe: Scribe is a server for aggregating log data streamed in real time from a large number of servers.)

  • 淘宝的实时数据传输平台(TimeTunnel http://code.taobao.org/p/TimeTunnel/wiki/index)

  • Evernote开放接口(GitHub - Evernote/evernote-thrift: Thrift IDL files for the Evernote Cloud API)

  • Quora(http://www.quora.com/Apache-Thrift)

  • HBase( HBase 官方文档 0.97 )

优点

  • 支持非常多的语言绑定

  • thrift文件生成目标代码,简单易用

  • 消息定义文件支持注释

  • 数据结构与传输表现的分离,支持多种消息格式

  • 包含完整的客户端/服务端堆栈,可快速实现RPC

  • 支持同步和异步通信

缺点

  • 和protobuf一样不支持动态特性

Apache Avro

Apache Avro 是一个二进制的数据序列化系统。实际上 Avro 除了序列化之外,像 MP 一样也提供了远程调用( RPC )功能。 Avro 是属于 Hadoop 的一个子项目,由 Hadoop 的 创始人 Doug Cutting 牵头开发,设计用于支持大批量数据交换的应用,依赖模式 (Schema) 来实现数据结构定义,模式由 JSON 对象来表示, Avro 也被作为一种 RPC 框架来使用。客户端希望同服务器端交互时,就需要交换双方通信的协议,它类似于模式,需要双方来定义,在 Avro 中被称为消息 (Message) 。通信双方都必须保持这种协议,以便于解析从对方发送过来的数据,这也就是传说中的握手阶段。

应用

  • Hadoop RPC (http://hadoop.apache.org/#What+Is+Apache+Hadoop%3F)

优点

  • 二进制消息,性能好/效率高

  • 使用JSON描述模式

  • 模式和数据统一存储,消息自描述,不需要生成stub代码(支持生成IDL)

  • RPC调用在握手阶段交换模式定义

  • 包含完整的客户端/服务端堆栈,可快速实现RPC

  • 支持同步和异步通信

  • 支持动态消息

  • 模式定义允许定义数据的排序(序列化时会遵循这个顺序)

  • 提供了基于Jetty内核的服务基于Netty的服务

缺点

  • 只支持Avro自己的序列化格式

  • 语言绑定不如Thrift丰富

YAML/INI (配置信息类,可用范围较弱)

参考资料

  • 跨语言通信方案的比较—Thrift、Protobuf和Avro https://www.cnblogs.com/kaleidoscope/p/10033328.html

  • Protobuf 和 Thrift 简介 https://www.cnblogs.com/hi3254014978/p/16704039.html

ChatGPT

c++有什么好用的序列化反序列化库,用于保存图形的属性等,需要考虑兼容

C++中有许多好用的序列化和反序列化库,用于保存图形的属性或其他对象的状态。以下是一些常用的序列化库:

  • JSON 库:JSON 是一种常用的数据交换格式,C++中有许多用于处理 JSON 的库,如 RapidJSON、nlohmann/json 等。这些库可以方便地将对象转换为 JSON 格式,并进行序列化和反序列化操作。

  • Protocol Buffers:Protocol Buffers 是一种高效的二进制序列化格式,由 Google 开发。它提供了一个定义数据结构的语言,并生成相应的序列化和反序列化代码。C++中的 protobuf 库可以方便地将对象转换为二进制格式,具有高效、紧凑和跨平台的特性。

  • MessagePack:MessagePack 是一种轻量级的二进制序列化格式,具有类似 JSON 的语法。C++中有许多支持 MessagePack 的库,如 msgpack-c、cereal 等。

  • Boost.Serialization:Boost.Serialization 是 Boost 库中提供的一个序列化库,支持将对象序列化为二进制格式或文本格式,并进行反序列化操作。它具有很好的兼容性和灵活性。

  • 这些库都具有不同的特点和用法,选择哪个库取决于你的需求和偏好。你可以根据具体情况来评估每个库的性能、易用性和兼容性,然后选择最适合你的项目的库。

    protobuf 如何保证属性变化后的兼容性

    Protocol Buffers 提供了一些机制来保证属性变化后的兼容性。以下是一些常用的方法:

  • 使用可选字段:将字段标记为 optional,表示该字段是可选的。这意味着可以在后续版本中添加或删除该字段,而不会影响旧版本的兼容性。如果读取旧版本的数据时发现字段不存在,可以使用默认值来填充。

  • 使用默认值:为字段设置默认值,在旧版本的数据中如果字段缺失时,会使用默认值。这样即使在新版本中添加了字段,旧版本的数据仍然可以正常解析。

  • 使用标识符:为字段分配唯一的标识符,这个标识符在字段被序列化和反序列化时用于识别字段。当旧版本的数据遇到未知的标识符时,可以选择忽略该字段或进行适当处理。

  • 使用扩展字段:使用扩展字段来处理未知的字段。通过定义扩展字段规则,可以在后续版本中添加新字段,而不会破坏旧版本的兼容性。

  • 版本控制:使用版本号来标识不同版本的消息格式。当序列化和反序列化时,可以根据版本号来选择不同的处理逻辑。

  • 需要注意的是,虽然这些机制可以帮助保证属性变化后的兼容性,但仍然需要谨慎处理版本升级的情况。在修改消息定义时,需要仔细考虑旧版本数据的兼容性,并进行充分的测试和验证。

    protobuf c++使用示例

    以下是一个简单的示例,演示如何在 C++ 中使用 Protocol Buffers(protobuf)库进行序列化和反序列化。

    首先,需要定义一个消息类型并编写相应的 .proto 文件。假设我们定义了一个简单的消息类型 Person,包含姓名和年龄两个字段:

    syntax = "proto3"; message Person { string name = 1; int32 age = 2; }

    接下来,使用 protoc 工具根据 .proto 文件生成 C++ 代码:

    $ protoc --cpp_out=. person.proto

    这将生成 person.pb.h 和 person.pb.cc 两个文件,包含了生成的 C++ 类和方法。

    现在可以在 C++ 代码中使用生成的类来序列化和反序列化消息。以下是一个简单的示例:

    #include <iostream> #include <fstream> #include "person.pb.h" using namespace std; int main() { // 创建一个 Person 消息对象 Person person; person.set_name("John Doe"); person.set_age(30); // 将消息对象序列化为字节流 string serializedData; person.SerializeToString(&serializedData); // 将字节流保存到文件 ofstream output("person.bin", ios::binary); output << serializedData; output.close(); // 从文件中读取字节流 ifstream input("person.bin", ios::binary); string inputData((istreambuf_iterator<char>(input)), (istreambuf_iterator<char>())); input.close(); // 反序列化字节流为消息对象 Person deserializedPerson; deserializedPerson.ParseFromString(inputData); // 输出反序列化后的消息字段 cout << "Name: " << deserializedPerson.name() << endl; cout << "Age: " << deserializedPerson.age() << endl; return 0; }

    在这个示例中,我们首先创建一个 Person 对象并设置姓名和年龄字段。然后,我们使用 SerializeToString 方法将对象序列化为字节流,并将字节流保存到文件中。

    接下来,我们从文件中读取字节流,并使用 ParseFromString 方法将字节流反序列化为 Person 对象。最后,我们输出反序列化后的姓名和年龄字段。

    protobuf的完整使用示例流程,含下载安装等

    下面是使用 Protocol Buffers(protobuf)的完整示例流程,包括下载、安装和使用 protobuf 的步骤:

  • 下载 Protocol Buffers 编译器和库:

    • 前往 Protocol Buffers GitHub 页面:Releases · protocolbuffers/protobuf · GitHub

    • 根据你的操作系统选择合适的预编译版本(例如,protoc-3.x.x-win64.zip 对于 Windows),并下载到本地。

  • 解压下载的文件:

    • 解压下载的压缩文件到你选择的目录。例如,在 Windows 上可以解压到 C:\protobuf 目录。

  • 将 protoc 编译器添加到系统路径(可选):

    • 将解压后的 protoc 编译器所在的目录路径(例如,C:\protobuf\bin)添加到系统的环境变量 PATH 中,这样可以在任意位置访问 protoc 命令。

  • 安装适用于你的编程语言的 protobuf 库:

    • 对于不同的编程语言,需要使用不同的库来与 protobuf 进行交互。你可以在官方的 protobuf GitHub 页面中找到各种语言的支持库和示例代码。

    • 例如,在 JavaScript 中,可以使用 npm 包管理器安装 protobufjs 包来处理 protobuf 消息。

  • 编写 .proto 文件:

    • 创建一个名为 example.proto 的文件,用于定义你的消息结构和服务等内容。在这个文件中,你可以定义消息的字段、类型、枚举和服务等。

  • 编译 .proto 文件:

    • 打开命令行终端,切换到包含 example.proto 文件的目录。

    • 运行以下命令来编译 .proto 文件,并生成对应编程语言的代码: protoc --proto_path=. --<language_out>=<output_dir> example.proto 其中 <language_out> 是你选择的编程语言(例如,java、python、cpp、js 等),<output_dir> 是生成的代码输出目录。

  • 使用生成的代码:

    • 根据你选择的编程语言和生成的代码,可以在你的应用程序中使用 protobuf 消息和相关函数。

    • 在代码中,你可以使用生成的类和方法来序列化、反序列化和操作 protobuf 消息。

  • 这是一个基本的 protobuf 使用示例流程。具体的步骤可能会因编程语言和具体需求而有所不同。你可以参考官方的 Protocol Buffers 文档和示例代码,以及相应编程语言的支持库的文档,来了解更多关于 protobuf 的使用方法和细节。

    qt项目中使用protobuf的实例

    以下是在 Qt 项目中使用 Protocol Buffers 的示例:

  • 下载和安装 Protocol Buffers:

    • 前往 Protocol Buffers GitHub 页面:Releases · protocolbuffers/protobuf · GitHub

    • 根据你的操作系统选择合适的预编译版本,并下载到本地。

    • 按照官方的说明进行安装。

  • 定义 .proto 文件:

    • 创建一个名为 example.proto 的文件,用于定义你的消息结构和服务等内容。在这个文件中,你可以定义消息的字段、类型、枚举和服务等。

  • 编译 .proto 文件:

    • 打开命令行终端,切换到包含 example.proto 文件的目录。

    • 运行以下命令来编译 .proto 文件,并生成对应的 C++ 代码: protoc --cpp_out=. example.proto

  • 创建 Qt 项目:

    • 打开 Qt Creator,创建一个新的 Qt 项目。

    • 在项目中创建一个用于存放生成的 .h 和 .cpp 文件的目录(例如,proto)。

  • 将生成的 .h 和 .cpp 文件添加到项目中:

    • 将生成的 example.pb.h 和 example.pb.cc 文件复制到刚刚创建的 proto 目录中。

    • 在 Qt Creator 中将这些文件添加到项目中,确保它们被编译。

  • 在项目中使用 Protocol Buffers:

    • 在需要使用 Protocol Buffers 的源文件中包含生成的 example.pb.h 头文件。

    • 在代码中使用生成的类和方法来序列化、反序列化和操作 protobuf 消息。

  • 示例代码:

    #include <QCoreApplication> #include "proto/example.pb.h" int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 创建一个 Message 对象 example::Person person; person.set_name("John Doe"); person.set_age(30); person.set_email("johndoe@example.com"); // 序列化为字节流 std::string serialized; person.SerializeToString(&serialized); // 反序列化为 Message 对象 example::Person deserialized; deserialized.ParseFromString(serialized); // 输出反序列化后的内容 qDebug() << "Name: " << QString::fromStdString(deserialized.name()); qDebug() << "Age: " << deserialized.age(); qDebug() << "Email: " << QString::fromStdString(deserialized.email()); return app.exec(); }

    在上述示例中,我们创建了一个名为 example 的 Protocol Buffers 消息,并对其进行序列化和反序列化操作。请注意,你需要根据实际情况修改 .proto 文件的定义和代码中的命名空间等内容。

    这是一个简单的示例,你可以根据实际需求在项目中使用 Protocol Buffers 来定义和操作自定义的消息。记得在项目中添加 Protocol Buffers 的依赖库,并在编译时链接到这些库。

    希望这个示例能帮助你在 Qt 项目中使用 Protocol Buffers。

    XML

    JSON

    TOML

    CSON

    需要做网站?需要网络推广?欢迎咨询客户经理 13272073477