在WCF中如何使用wsHttp传输大量的数据有效载荷(序列化对象),并提供消息安全性?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (31)

我有一个案例,我需要使用wsHttp使用WCF 传输大量的序列化对象图(通过NetDataContractSerializer)。我正在使用邮件安全并希望继续这样做。使用这种设置,我想传输序列化的对象图,有时可能会接近300MB左右,但是当我尝试这样做时,我已经开始看到System.InsufficientMemoryException类型的异常出现。

经过一番研究,默认情况下,在WCF中默认情况下,服务调用的结果默认包含在单个消息中,其中包含序列化的数据,并且该数据在服务器上默认缓冲,直到整个消息被完整写入。因此,内存异常是由于服务器内存资源不足而导致的,因为该缓冲区已满,因此可以分配内存资源。我遇到的两个主要建议是使用流式处理或分块来解决这个问题,但我不清楚这涉及到什么以及是否可以使用我当前的设置(wsHttp / NetDataContractSerializer / Message Security)解决任何解决方案。到目前为止,我知道使用流式消息安全性是行不通的,因为消息加密和解密需要处理整个数据集而不是部分消息。然而,块化听起来可能是可能的,但是我不清楚它将如何处理我列出的其他约束条件。如果有人能提供一些关于可用解决方案和如何实施的指导,我将不胜感激。

我应该补充一点,在我的情况下,我真的不担心与其他客户端的互操作性,因为我们拥有并控制通信的每一侧,并使用共享接口模式将数据传输到任何一方。所以我愿意接受任何适合使用带有消息安全性的wsHttp来限制使用NetDataContractSerializer序列化的对象图的想法,我更喜欢一个解决方案,我不需要大幅改变我现有的服务和周围的基础设施。

相关资源:

我也对这种数据可以完成的任何类型的压缩感兴趣,但是看起来我可能最好在传输层次上做这件事,一旦我可以转换到.NET 4.0中,以便客户端将自动支持gzip标题,如果我正确理解这一点。

关于我如何得出缓冲消息过大的结论导致了我的问题。最初我在测试时看到了下面的CommunicationException

底层连接已关闭:连接意外关闭。

最终在运行这个并做了更多日志记录之后,我发现了引起指定消息的问题的底层InsufficientMemoryException异常。

无法分配268435456字节的托管内存缓冲区。可用内存量可能很低。

源于以下方法。

System.ServiceModel.Diagnostics.Utility.AllocateByteArray(Int32大小)

换句话说,失败来自分配数组。当写入相同的数据序列化到磁盘时,它需要大约146MB,如果我把它减半,然后我不会得到错误,但我没有挖掘更多的特定阈值,打破我的缓冲区,是否特定于我的系统或不。

我想在这一点上,我正在寻找以下的一些澄清。我的理解是默认情况下WCF wsHttp具有消息安全性,因此在将响应发送回客户端并因此导致我的问题之前,需要在服务器上缓冲整个消息(通常是我返回的整个数据集)。

可能的解决方案:

  • 限制数据大小 - 通过使用某种形式的压缩,编码或限制实际数据的方式使用某种分页方法返回,以避免消耗传出缓冲区的最大容量。
  • 流式传输 - 允许大量数据通过WCF以流方式发送,但这与wsHttp或MessageSecurity不兼容,因为这些技术需要缓冲所有数据。
  • 分块信道 - 允许将数据分解为单独的消息,但此时我不确定这对服务合同设计有何限制,以及我是否仍然可以使用带消息绑定的wsHttp。

限制我可以返回的数据只能工作到某一点,并且与Streaming选项一样,这些选项要求在WCF服务调用之外编码许多较低级别的工作。所以我想我需要知道的是,组块通道的任何可能实现是否可以通过允许在服务器上将单独一组数据分解成单独的消息然后在客户端上拼凑在一起来旁路大信息问题这样我不必更改现有服务契约的接口/形状,并且使得该流程对于每个服务实现的客户端和服务器部分几乎都是隐藏的,同时仍然使用消息安全和wsHttp。如果组块通道要求我重写我的服务合约以暴露流,那么我不会' 看看这与Streaming解决方案有何不同。如果有人可以为我回答这些问题,我会给他们奖金,并将其标记为答案。

提问于
用户回答回答于

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

用户回答回答于

protobuf-net通常对大多数数据具有显着的节省空间(如:数量级),并且可以附加到WCF。不幸的是,目前它不支持完整的图表,只有树木。但是,我在那里有计划,我根本没有时间去实施。我无法承诺任何事情,但我可以尽快提前解决这个问题。

除此以外; 可能有办法调整现有的代码以使用树而不是图。

扫码关注云+社区