简体   繁体   English

在缓冲模式下使用WCF发送大字节[]时,内存分配失败

[英]Memory allocation failed on sending Large byte[] using WCF in buffered mode

I want to use WCF for transfer file between clients and server. 我想使用WCF在客户端和服务器之间传输文件。 I read many article that some people using Stream mode for this purpose. 我读了许多文章,有人为此目的使用Stream模式。 but for it's restrictions I decide to create service with buffered mode. 但出于限制,我决定以缓冲模式创建服务。 For example consider this: 例如,考虑以下情况:

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

server web config: 服务器Web配置:

...
<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>

and client config: 和客户端配置:

<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>

I can upload 400MB file but when the size of file is 500MB or above I got this error: 我可以上传400MB文件,但是当文件大小为500MB或以上时,出现此错误:

System.InsufficientMemoryException HResult=0x8013153D Message=Failed to allocate a managed memory buffer of 1073741824 bytes. System.InsufficientMemoryException HResult = 0x8013153D消息=无法分配1073741824字节的托管内存缓冲区。 The amount of available memory may be low. 可用内存量可能不足。 Source=mscorlib 来源= mscorlib程序

Inner Exception 1: OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. 内部异常1:OutOfMemoryException:引发了类型为'System.OutOfMemoryException'的异常。 \\ \\

I think I set values for 2GB data but it fails on 500MB . 我想我为2GB数据设置了值,但是500MB上却失败了。

Thanks 谢谢

this code run locally and I have 16GB RAM. 此代码在本地运行,我有16GB RAM。 Where is the problem and what value I should change to upload harge files? 问题出在哪里,上传harge文件应该更改什么值?

Thanks 谢谢

I remember I was working with a large file transfer, and I used buffered mode to transfer but was not the best solution because after a while I got some exception about memory leak or something related memory, I changed it to transferMode="Streamed" and everything worked fine, by the buffered mode it means that the entire content of a message is present in memory before it is sent or after it is received. 我记得我当时正在处理大型文件传输,并且我使用buffered模式进行传输,但不是最佳解决方案,因为一段时间后,我遇到了有关内存泄漏或某些相关内存的异常,我将其更改为transferMode="Streamed" ,一切正常,通过buffered模式,这意味着消息的全部内容在发送之前或接收之后都存在于内存中。 While that is a good strategy for most scenarios, and necessary for messaging features such as digital signatures and reliable delivery, large messages could exhaust a system's resources. 尽管对于大多数情况而言,这是一个很好的策略,并且对于诸如数字签名和可靠传递之类的消息传递功能而言是必需的,但大消息可能会耗尽系统的资源。
take a look at here . 看一下这里

To avoid creating new buffers all the time WCF uses BufferManager to reuse buffers, up to the limit specified by maxBufferPoolSize , buffers are expensive to create and destroy. 为了避免在WCF 始终使用BufferManager重用缓冲区时一直创建新缓冲区,直到maxBufferPoolSize指定的限制, buffers的创建和销毁都是昂贵的。 You can use the BufferManager class to manage a buffer pool. 您可以使用BufferManager类来管理缓冲池。

You can try increasing maxBufferPoolSize to see if you can reduce memory usage. 您可以尝试增加maxBufferPoolSize来查看是否可以减少内存使用量。 I strongly recommend do not increase it to max because I think buffers from the pool are never released until the app-domain get recycles. 我强烈建议不要将其增加到最大值,因为我认为在应用程序域得到回收之前,池中的缓冲区永远不会释放。 A period of high traffic could cause a lot of memory to be used and never released. 一段时间的高流量可能会导致大量内存被使用而从未释放。

So I recommend you to use streamed mode to transfer large file. 因此,我建议您使用streamed模式传输大文件。

To split files and works with large streams below links may help you: 要拆分文件并使用大型流,请使用下面的链接可以帮助您:

Multiple file in one Stream, custom stream 一个流中有多个文件,自定义流
Best way to return large file as split zip files,Stream or Byte array WCF 将大文件作为拆分的zip文件,流或字节数组WCF返回的最佳方法

it may also help you 它也可能对您有帮助

Multiple stream in one stream will not passed to client properly 一个流中的多个流不会正确传递给客户端

OutOfMemoryException says the process is using the maximum memory it is allowed to. OutOfMemoryException表示进程正在使用允许的最大内存。 Are you debugging the code whilst trying to upload this large file? 您是否在尝试上载此大文件时调试代码? Your IDE might be causing this problem. 您的IDE可能导致此问题。 Moreover, in my opinion, when uploading large files the best approach is to split the file into smaller buffers and re-create them in the server side. 而且,我认为,上载大文件时,最好的方法是将文件拆分为较小的缓冲区,然后在服务器端重新创建它们。 Another approach can use FTP between the server and the client for handling the upload-download itself. 另一种方法可以在服务器和客户端之间使用FTP处理自身的上载下载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM