【问题标题】:Memory allocation failed on sending Large byte[] using WCF in buffered mode在缓冲模式下使用 WCF 发送大字节 [] 时内存分配失败
【发布时间】:2019-01-19 07:29:03
【问题描述】:

我想使用WCF 在客户端和服务器之间传输文件。我读了很多文章,有些人为此目的使用Stream 模式。但由于它的限制,我决定使用缓冲模式创建服务。例如考虑一下:

[OperationContract]
void UploadFile(Guid systemKey, string fileName, byte[] fileContent, string userName);

服务器网络配置:

...
<system.web>
    <compilation debug="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" maxRequestLength="2147483647" executionTimeout="7200"/>
</system.web>
....
<bindings>
  <basicHttpBinding>
    <binding name="myBasicBinding" maxBufferSize="2147483647" 
                                   maxReceivedMessageSize="2147483647" 
                                   closeTimeout="01:50:00" 
                                   openTimeout="01:50:00" 
                                   sendTimeout="01:50:00" 
                                   receiveTimeout="01:50:00" 
                                   messageEncoding="Mtom">
      <readerQuotas maxDepth="128" maxStringContentLength="8388608" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    </binding>
  </basicHttpBinding>
</bindings>
....
<system.webServer>
   <security>
      <requestFiltering>
           <requestLimits maxAllowedContentLength="4294967295"/>
      </requestFiltering>
   </security>
   <modules runAllManagedModulesForAllRequests="true"/>
   <directoryBrowse enabled="true"/>
</system.webServer>

和客户端配置:

<system.web>
    <compilation debug="true" targetFramework="4.6"/>
    <httpRuntime targetFramework="4.6" maxRequestLength="2147483647" executionTimeout="7200"/>
</system.web>
...
<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="4294967295"/>
      </requestFiltering>
    </security>
</system.webServer>
<system.serviceModel>
    <bindings>
        <basicHttpBinding>
        <binding name="basicEndpoint"
                 maxBufferSize="2147483647"
                 maxReceivedMessageSize="2147483647"
                 closeTimeout="01:50:00"
                 openTimeout="01:50:00"
                 sendTimeout="01:50:00"
                 receiveTimeout="01:50:00"
                 messageEncoding="Mtom">
          <readerQuotas maxDepth="128" maxStringContentLength="8388608" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
       </binding>
     </basicHttpBinding>
   </bindings>
   <client>
      <endpoint address="http://localhost/fts.svc" binding="basicHttpBinding" bindingConfiguration="basicEndpoint" contract="ServiceReference1.Ifts" name="basicEndpoint"/>
   </client>
</system.serviceModel>

我可以上传400MB 文件,但是当文件大小为500MB 或以上时,我收到此错误:

System.InsufficientMemoryException H结果=0x8013153D 消息=未能分配 1073741824 字节的托管内存缓冲区。可用内存量可能很低。 来源=mscorlib

内部异常 1: OutOfMemoryException:引发了“System.OutOfMemoryException”类型的异常。 \

我想我为2GB 数据设置了值,但它在500MB 上失败了。

谢谢

这段代码在本地运行,我有16GB RAM。问题出在哪里,我应该更改什么值来上传硬文件?

谢谢

【问题讨论】:

  • 我认为问题出在BufferManager,大对象实际上是由WCF分配的,从未被释放,所以导致内存泄漏异常,最好使用streamed模式。

标签: c# wcf wcf-binding c#-7.0 .net-4.6


【解决方案1】:

我记得我正在处理一个大文件传输,我使用buffered 模式传输但不是最好的解决方案,因为过了一段时间我遇到了一些关于内存泄漏或相关内存的异常,我将其更改为@ 987654329@ 一切正常,buffered 模式意味着消息的全部内容在发送之前或接收之后都存在于内存中。虽然这对于大多数情况来说都是一个很好的策略,并且对于数字签名和可靠传递等消息传递功能来说是必要的,但大型消息可能会耗尽系统的资源。
看看here。

为了避免在 WCF 使用 BufferManager 重用缓冲区时一直创建新缓冲区,达到 maxBufferPoolSize 指定的限制, buffers 的创建和销毁成本很高。您可以使用BufferManager 类来管理缓冲池。

您可以尝试增加maxBufferPoolSize,看看是否可以减少内存使用量。我强烈建议不要将其增加到最大值,因为我认为池中的缓冲区在应用程序域得到回收之前永远不会释放。一段时间的高流量可能会导致大量内存被使用而从未释放。

所以我推荐你使用streamed模式来传输大文件。

拆分文件并使用以下链接处理大流可能会对您有所帮助:

Multiple file in one Stream, custom stream
Best way to return large file as split zip files,Stream or Byte array WCF

也许对你有帮助

Multiple stream in one stream will not passed to client properly

【讨论】:

    【解决方案2】:

    OutOfMemoryException 表示进程正在使用它允许的最大内存。您是否在尝试上传这个大文件时调试代码?您的 IDE 可能会导致此问题。 此外,在我看来,上传大文件时,最好的方法是将文件拆分为较小的缓冲区,然后在服务器端重新创建它们。 另一种方法是在服务器和客户端之间使用 FTP 来处理上传-下载本身。

    【讨论】:

    • 谢谢,但问题在于缓冲模式 maxBufferSize 和 maxReceivedMessageSize 必须相同,如果我减少 maxBufferSize 的数量,maxReceivedMessageSize 的数量也会减少
    • OutOfMemoryException 只是表示无法分配一块连续的内存。这可能是由于内存碎片造成的。
    猜你喜欢
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    相关资源
    最近更新 更多