我有一个案例,我需要使用wsHttp使用WCF 传输大量的序列化对象图(通过NetDataContractSerializer).我正在使用邮件安全性,并希望继续这样做.使用这个设置我想传输序列化的对象图,有时可以接近300MB左右但是当我尝试这样做时,我开始看到System.InsufficientMemoryException类型的异常出现.
经过一些研究后,默认情况下,WCF中默认情况下,服务调用的结果默认包含在单个消息中,其中包含序列化数据,并且默认情况下在服务器上缓冲此数据,直到完整写入整个消息.因此,内存异常是由于服务器的内存资源不足而导致分配的,因为该缓冲区已满.我遇到的两个主要建议是使用流式传输或分块来解决这个问题,但是我不清楚这涉及到什么,以及我的当前设置是否可以使用任何解决方案(wsHttp/NetDataContractSerializer/Message Security).到目前为止,我理解使用流式消息安全性不起作用,因为消息加密和解密需要处理整个数据集而不是部分消息.然而,Chunking听起来似乎有可能,但是我不清楚如何使用我列出的其他约束来完成它.如果有人可以就可用的解决方案以及如何实施它提供一些指导,我将非常感激.
我应该补充一点,在我的情况下,我真的不担心与其他客户端的互操作性,因为我们拥有并控制通信的每一面,并使用共享接口模式传输到任何一方的数据.所以我愿意接受任何符合使用带有消息安全性的wsHttp以转移使用NetDataContractSerializer序列化的对象图的约束的想法,我更喜欢一个解决方案,我不需要大幅改变我现有的服务和周围的基础设施.
相关资源:
我也对可以对这些数据进行的任何类型的压缩感兴趣,但看起来我可能最好在传输级别执行此操作,一旦我可以转换到.NET 4.0,以便客户端将自动支持gzip标题如果我理解正确的话.
关于如何在结论中得出缓冲消息太大导致我的问题的一些历史.最初我在测试时看到了下面的CommunicationException.
底层连接已关闭:连接意外关闭.
最后,在运行此操作并进行更多日志记录后,我发现了导致指定消息出现问题的基础InsufficientMemoryException异常.
无法分配268435456字节的托管内存缓冲区.可用内存量可能很低.
其中源于以下方法.
System.ServiceModel.Diagnostics.Utility.AllocateByteArray(Int32 size)
所以在其他方面,失败来自分配阵列.当写入序列化到磁盘的相同数据时,它需要大约146MB,如果我将其减少一半,那么我就会停止获取错误但是我没有更多地挖掘破坏我的缓冲区的特定阈值以及它是否特定于我的系统或不.
我想在这一点上我正在为以下内容寻找一些澄清.我的理解是,默认情况下WCF wsHttp具有消息安全性,在响应被发送回客户端之前需要在服务器上缓冲整个消息(通常是我正在返回的整个数据集),从而导致我的问题.
可能的解决方案:
限制我可以返回的数据只能达到某一点,并且与Streaming选项一样,这些选项需要在WCF服务调用之外编写许多较低级别的工作.所以我想我需要知道的是,通过允许将一组数据分解为服务器上的单独消息然后在客户端上拼凑在一起,是否任何可能的分块通道实现都可以解决大型消息问题.这样一种方式,我不必改变现有服务合同的接口/形状,并且在仍然使用消息安全性和wsHttp的同时,几乎隐藏了每个服务实现的客户端和服务器部分的过程.如果分块通道要求我重新编写我的服务合同以暴露流,那么我不会 看看这与Streaming解决方案有什么不同.如果有人可以简单地为我回答这些问题,我会给予奖励,并将其标记为答案.
wcf large-data-volumes chunking wshttpbinding netdatacontractserializer