使用带有消息安全性的WCF中的wsHttp传输大量有效数据(序列化对象)

时间:2010-06-10 16:39:01

标签: wcf large-data-volumes wshttpbinding chunking netdatacontractserializer

5 个答案:

答案 0 :(得分:3)

protobuf-net在大多数数据上通常具有显着节省空间(如:数量级),并且可以附加到WCF。不幸的是目前它不支持完整的图形,只支持树木。但是,我有计划,我根本没有时间实施。我无法承诺任何事情,但我可以尝试更快地完成这项工作。

否则;可能有一些方法可以调整现有代码以使用树而不是图形。

答案 1 :(得分:2)

如果您仍想使用Message Security,我建议您使用MTOM优化传输消息所需的网络带宽,以及在应用安全性时使用较小内存缓冲区的分块通道。否则,WCF将尝试在内存中加载整个消息以应用安全性,因此您将获得内存不足的异常。

答案 2 :(得分:2)

我曾经实现过将大文本传递到wcf或从wcf传递大文本。我的trig将它转换为流并使用GZipStream压缩它然后将其作为byte []发送,幸运的是它永远不会超过10 MB。

在你的情况下,我建议做碎片。将Serialized对象转换为byte [],然后将其合并并解压缩

psudo

int transferSize = 5000000; // 5MB
byte[] compressed = ...;
var mem = new System.IO.MemoryStream(compressed);

for(int i = 0; i < compressed .length; i+= transferSize )
{
    byte[] buffer = new byte[transferSize];
    mem.Read(buffer, i, compressed);
    mem.Flush();
    sendFragmentToWCF(buffer);
}

编辑2010年12月8日

基于我的理解,情况是客户端是通过WCF下载一些大的序列化对象。 我没有特别测试这个解决方案,但猜测它应该工作。关键是将序列化对象保存到文件并使用Response传输该文件。

[WebMethod]
public void GetSerializedObject()
{
    string path = @"X:\temp.tmp";

    var serializer = new  System.Runtime.Serialization.NetDataContractSerializer();
    var file = new System.IO.FileStream(path, System.IO.FileMode.CreateNew);

    try
    {
        serializer.Serialize(file, ...);
        this.Context.Response.TransmitFile(path);
        this.Context.Response.Flush();
    }
    finally
    {
        file.Flush();
        file.Close();
        file.Dispose();
        System.IO.File.Delete(path);
    }
}

WCF会自动执行文件流式传输,因为我们使用文件传输,所以不必担心序列化对象大小。别忘了配置响应限制。

答案 3 :(得分:0)

一些较轻但不保证的解决方案是

  • 使用DataContractSerializer,因为您拥有双方。这不需要嵌入式类型信息,这非常大。
  • 再次使用[DataMember(EmitDefaultValue = false)]讨论in a question I asked - 再次因为您拥有双方;这样做会减少一些消息大小(当然多少取决于图中默认的字段数)。
  • 使用[DataContract(IsReference=true)],特别是如果您有许多重复值对象或参考数据
  • 在服务器上使用某种限制来减少同步结果的内存压力

这些当然是权衡,例如具有可读性。

答案 4 :(得分:0)

由于没有人将其付诸实施,因此使用WebSocketslong polling技术或许可以解决此问题。我只是简单地研究了这些解决方案,并没有围绕它们制定解决方案,但我想提出这些概念进行记录,如果时间允许,我会在稍后的时间点扩展我的答案。

基本思想是实现类似于ChunkingChannel示例如何工作的想法,但不需要全双工通道,这通常会破坏端口80基于Web的请求/响应模型,这是避免必须进行的防火墙和客户端的其他相关配置。

其他相关材料:

更新:在对此进行更多研究后,似乎通过使用称为NetHttpBinding的WebSockets,我本来就不会解决在WCF中使用带有消息安全性的wsHttp的原始请求。我将在这里保留我的答案,但作为其他可能正在寻找替代方案的人的信息。