【发布时间】:2015-03-06 16:42:46
【问题描述】:
在我的流式 WCF 应用程序中,我在我的服务中获得 System.OutOfMemoryExceptions 以获取大消息(使用数据读取器查询 >7GB MSSQL 表,消息甚至可能超过 7GB),而小消息工作正常。我可以观察到在执行DataReaderToExcelXml 期间内存使用量不断增长(见下文)。奇怪的是,它通常会快速增长到 2GB,保持在 2GB +-1GB 一段时间(1-5 分钟),然后再次快速增长到 ~6.5GB,这会导致异常(机器有 8GB 内存)。在这一点上,在我看来,好像 Stream 不再通过,而是被缓冲了。
我已经启用了跟踪日志记录,但它似乎因异常而停止。 DataReaderToExcelXml 函数调用是跟踪日志中的最后一个可见事件。
在 WCF 消息契约中,我确保消息只包含 Stream。在客户端,返回的 Stream 被简单地读取、写入文件流并处理。但是,当我得到异常时,我永远无法观察到正在执行的客户端代码或正在写入的文件。
我已经尝试在客户端和服务器端将maxBufferPoolSize 设置为零,如https://stackoverflow.com/a/595871/4166885 所述。没有成功。
WCF 服务端的流写入器功能:
Public Shared Function DataReaderToExcelXml(ByRef dr As SqlDataReader) As Stream
Dim ms As New MemoryStream
Dim tw As New IO.StreamWriter(ms)
For Each row As DbDataRecord In dr
'Embed row in ExcelXml, detailed function omitted
tw.write(row.toString()) 'row.toString is just a simplification
End While
tw.Flush()
dr.Close()
ms.Seek(0, SeekOrigin.Begin)
Return ms
End Function
Web.config 绑定
<bindings>
<basicHttpBinding>
<binding receiveTimeout="24.00:00:00" sendTimeout="24.00:00:00"
maxBufferPoolSize="9223372036854775807" maxReceivedMessageSize="9223372036854775807"
messageEncoding="Mtom" transferMode="Streamed" bypassProxyOnLocal="True">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
App.config 绑定
<binding name="BasicHttpBinding_IFileService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="24.00:00:00" sendTimeout="24.00:00:00"
allowCookies="false" bypassProxyOnLocal="true" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="8589934592" messageEncoding="Mtom"
textEncoding="utf-8" transferMode="Streamed">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
编辑:在我的服务上使用 .NET 内存分析器我发现,内存量的增加可以追溯到类型 byte[]。就我个人而言,这对我没有任何意义,但也许它是有用的信息。
edit2:在检查 System.OutOfMemoryException 时,我注意到它发生在 ms.Capacity = ms.length = 1073741824 = 1GB 时。因此,就在内存流将其容量翻倍之前。我仍然不确定,为什么 w3wp 一开始会消耗如此大量的内存,但现在很明显内存流触发了 Exception。
【问题讨论】:
标签: vb.net wcf streaming out-of-memory