谷歌协议缓冲区和HTTP

46

我正在使用gSoap将传统的C++系统重构为SOA。我们有一些性能问题(非常大的XML文件),因此我的主管要求我看看协议缓冲区。我看了一下,它看起来非常酷(我们需要C++和Java支持)。然而,协议缓冲区仅是用于序列化的解决方案,现在我需要将其发送到Java前端。从C++和Java的角度来看,我应该使用什么方法来通过HTTP(仅限内部网络)发送这些序列化内容?

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


FYI。性能问题已与gsoap团队讨论(我参与了此次讨论),我们建议使用SOAP_XML_TREE标志或使用-DWITH_NOIDREF进行编译。如果没有此标志,则由于SOAP编码具有多个ref元素(id-ref)来序列化图形(即检测共同引用的对象,分析循环数据结构等),性能可能会大大降低。建议的标志关闭此功能以将XML序列化为树形结构。消息传递速度得到极大提高。性能的唯一瓶颈是网络延迟和带宽。 - Dr. Alex RE
@Alex SOAP仍在更新?这真的很令人印象深刻!那个问题已经有7年了,所以不会对其采取行动 :) - Nazgob
据我所知,自2005年以来,每个人都已经阅读了FAQ,并得出了这个建议。您为什么认为这是最近的发展? - Dr. Alex RE
@alex 我没有阅读那个常见问题解答,所以你的论点不可能是正确的,显然并不是每个人都读过它。而且这也与我所说的只对协议缓冲区感兴趣无关。 - Nazgob
5个回答

72

您可以通过HTTP请求或HTTP响应发送二进制负载。只需将协议缓冲区的字节直接写入请求/响应中,并确保将内容类型设置为“application/octet-stream”。客户端和服务器可以轻松处理其余内容。我认为在任何一端都不需要更多特殊处理。


42
我们正在使用在这里第21页所述的application/x-protobuf格式:http://www.slideshare.net/mokeefe/javaone-2009-ts5276-restful-protocol-buffers - Tim Sylvester
1
啊,太好了。我不知道有人建议为它设置 MIME 类型。 - Sean Owen
7
以“x-”开头的MIME类型通常不是标准格式,通常被视为应用程序/八位二进制流处理。 - n0rd
14
看起来在 ProtoRPC 项目中有一次提交(2012 年 4 月)说明现在 application/octet-stream 是首选的内容类型。 - Tommy Stanton
如果你有自己的客户端和服务器,那么是可以保证的;否则就不能保证。 - Alex Bitek

25

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。我们像这样定义一个信封:
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中。


10

Google前端偏爱application/protobuf

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


7
你可以将protobuf编码的数据序列化/反序列化为字符串。将序列化后的字符串作为HTTP POST请求的主体发送到Java并进行反序列化。这是一种方法。另一种方法是利用protobuf服务接口。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

2
据我所知,协议缓冲区支持C++和Java两种语言,因此您应该能够在这两个系统之间交换协议缓冲区序列化数据。
不过,您似乎真正想问的问题是“如何在C++后端和Java客户端之间通过HTTP发送数据”。
听起来您需要学习如何使用gSOAP,请阅读文档
或者,您可以从您的C++应用程序托管一个RESTful web服务器:请参考https://stackoverflow.com/questions/298113/how-can-i-implement-a-restful-webservice-using-c++
接下来,您需要访问托管在新的C++ RESTful服务器上的数据:请参考Java的Rest客户端?

2
gSOAP过于复杂化这个问题了。在原生二进制格式中,Protobufs在HTTP上运行良好。 - Will
过于复杂了吗?如果你想传输二进制内容,那就使用Protobufs和REST。但对于XML,它使我们的工作变得更加容易。WSDL、SOAP和XML的复杂部分都已经被处理好了。此外,我们使用gsoap每秒可以进行超过5,000次服务调用。主要的开销在于TCP/IP,而不是gsoap堆栈。 - Dr. Alex RE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接