【问题标题】:Google Protocol Buffers and HTTPGoogle 协议缓冲区和 HTTP
【发布时间】:2010-11-28 09:29:19
【问题描述】:

我正在使用 gSoap 将遗留 C++ 系统重构为 SOA。我们有一些性能问题(非常大的 XML),所以我的领导让我看看协议缓冲区。我做到了,它看起来很酷(我们需要 C++ 和 Java 支持)。但是协议缓冲区只是用于序列化的解决方案,现在我需要将它发送到 Java 前端。从 C++ 和 Java 的角度来看,我应该使用什么来通过 HTTP(只是内部网络)发送这些序列化的内容?

PS。另一个人试图加速我们的 gSoap 解决方案,我只对协议缓冲区感兴趣。

【问题讨论】:

  • 仅供参考。与 gsoap 团队讨论了性能(我参与了这个),我们建议使用SOAP_XML_TREE 标志或使用-DWITH_NOIDREF 编译。如果没有这个标志,性能可能会低得多,因为 SOAP 编码使用多引用元素 (id-ref) 来序列化图形(即检测共同引用的对象、分析循环数据结构等)。建议的标志关闭此功能以将 XML 序列化为树。消息传递速度大大提高。性能的唯一瓶颈是网络延迟和带宽。
  • @Alex SOAP 还在更新吗?这实际上令人印象深刻!这个问题已经 7 岁了,所以不会采取行动:)
  • 据我所知,其他人都已阅读包含此建议的常见问题解答(自 2005 年以来)。是什么让您相信这是最近的事态发展?
  • @alex 我没有阅读那个常见问题解答,所以你的论点不可能是真的,显然不是每个人都读过它。它也无关紧要,因为我说我只对协议缓冲区感兴趣。

标签: java c++ http protocol-buffers


【解决方案1】:

您当然可以通过 HTTP 请求或在 HTTP 响应中发送二进制有效负载。只需将协议缓冲区的字节直接写入请求/响应中,并确保将内容类型设置为“application/octet-stream”。客户端和服务器应该能够轻松地处理其余部分。我认为你不需要任何比这更特别的东西。

【讨论】:

  • 我们正在使用application/x-protobuf,如幻灯片 21 所述:slideshare.net/mokeefe/…
  • 啊更好。不知道有人建议了 MIME 类型。
  • 名称以“x-”开头的 MIME 类型远非标准,通常被视为 application/octet-stream。
  • 看起来在 ProtoRPC 项目中有 a commit in Apr 2012 声明 application/octet-stream 是当今首选的内容类型。
  • @znlyj 如果你有自己的客户端和服务器,可以,否则不保证。
【解决方案2】:

ProtoBuf 是一个二进制协议。它不能与 SOAP 很好地混合。我建议您要么坚持使用 gSOAP,要么完全转换为 ProtoBuf。

使用 protoBuf,您可以像这样以特殊格式定义协议,

message Product {
  required string id = 1;
  required string description = 2;
  required int32 quantity = 3;
  optional bool discontinued = 4;
}

protoc 工具可以在 C++/Java/Python 中生成代码,因此您可以在一端序列化它并在另一端反序列化。

如您所见,ProtoBuf 旨在序列化单个对象。它不提供 SOAP 提供的所有功能,例如标头。为了解决这个问题,我们在 ProtoBuf 中使用了 ProtoBuf。我们这样定义一个Envelope,

message Envelope {
  enum Type { 
    SEARCH = 1;
    SEARCH_RESPONSE = 2;
    RETRIEVE = 3;
    RETRIEVE_RESPONSE = 4; 
  }
  required Type type = 1;

  required bytes encodedMessage = 2;

  message Header {
    required string key = 1;
    required bytes value = 2;
  }    
  repeated Header headers = 3;
}

encodedMessage 是另一个序列化的 ProtoBuf 消息。 SOAP 标头中的所有内容现在都转到headers

【讨论】:

    【解决方案3】:

    Google 前端更喜欢application/protobuf

    Google API 客户端的ProtocolBufferModel 使用application/x-protobuf

    【讨论】:

      【解决方案4】:

      您可以将 protobuf 编码数据序列化/反序列化到/从字符串中。将序列化的字符串作为 HTTP POST 的主体发送到 Java 并对其进行反序列化。这是一种方法。另一种方法是使用 protobuf Service 接口。 Protobuf 允许您在 .proto 文件中定义服务接口,并且协议缓冲区编译器将以您选择的语言生成服务接口代码和存根。你只需要实现 protobuf::RpcChannel 和 protobuf::RpcController 类就可以得到一个完整的 RPC 框架。或许您可以为这些类编写一个 HTTP 包装器。有关详细信息,请参阅以下链接:

      http://code.google.com/apis/protocolbuffers/docs/proto.html#services http://code.google.com/apis/protocolbuffers/docs/reference/cpp-generated.html#service http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.service.html

      【讨论】:

        【解决方案5】:

        据我所知,C++ 和 Java 都支持协议缓冲区,您应该能够在两个系统之间交换协议缓冲区序列化数据。

        也就是说,您真正的问题似乎是“如何在 C++ 后端和 Java 客户端之间通过 HTTP 发送内容”

        听起来您需要学习如何使用 gSOAP,请阅读docs

        或者,您可以从您的 C++ 应用程序托管一个 RESTful Web 服务器:看看这个:https://stackoverflow.com/questions/298113/how-can-i-implement-a-restful-webservice-using-c++

        接下来,您需要访问托管在新 C++ RESTful 服务器上的数据:看这个:Rest clients for Java?

        【讨论】:

        • gSOAP 使问题变得非常复杂。 Protobufs 在其原生二进制格式的 HTTP 上运行良好。
        • 过于复杂?当然,如果您想传输二进制内容,那么只需使用 Protobufs 和 REST。但是对于 XML,它使我们的工作变得容易得多。 WSDL、SOAP 和 XML 的复杂部分都得到了处理。此外,我们使用 gsoap 每秒获得​​超过 5,000 次服务调用。主要开销是 TCP/IP,而不是 gsoap 堆栈。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-20
        • 2010-12-15
        • 1970-01-01
        相关资源
        最近更新 更多