从WCF上传和下载大量对象

时间:2012-08-08 06:27:41

标签: c# wcf .net-4.0

我是.NET,C#和WCF的新手,我正在尝试创建一个服务,它将公开允许上传和下载大量对象(对象数组)的方法。我在WCF中看到了很多关于大文件传输的帖子,但我似乎无法找到任何专注于上传和下载大量可序列化对象的内容。

我已经能够" hack up"允许字节和超时限制等的web.config文件,但我想知道是否有更好的方法来配置WCF以获得更好的速度和内存使用以允许这种传输。因为我已经根据我的测试结果配置了web.settings(如果超出超时/字节限制,用一些疯狂的大数字等增加限制)我怀疑我的配置是否有意义。

其次,我已经看到了一些实现选项,比如绑定TransferMode = Streaming or MTOM,但我不知道它们是否会适用于我的场景。有人可以指出我正确的方向吗?

抱歉,我可能没有很好地构建我的问题,但我们将非常感谢您的想法。

以下是我的web.config设置:

<system.web>
    <httpRuntime maxRequestLength="409600000" executionTimeout="360000"/>
    <compilation debug="true" targetFramework="4.0"  />
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHTTP" closeTimeout="00:01:00" receiveTimeout="01:00:00"
          sendTimeout="01:00:00" maxBufferSize="655360000" maxReceivedMessageSize="655360000"
          messageEncoding="Text" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="WebService.WebService">
        <endpoint address="" behaviorConfiguration="BasicEndPoint" binding="basicHttpBinding"
          bindingConfiguration="BasicHTTP" name="BasicHTTP" contract="WebService.IWebService" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="BasicEndPoint">
          <dataContractSerializer maxItemsInObjectGraph="65536000" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"  />
  </system.serviceModel>
 <system.webServer>
   <security>
     <requestFiltering>
       <requestLimits maxAllowedContentLength="204800000" />
     </requestFiltering>
   </security>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

2 个答案:

答案 0 :(得分:1)

我建议仅将流模式用于视频/音频流等类似的任务,当你真正拥有主机上的流时,你真的需要在客户端接收流。 对于任何其他任务,我会使用缓冲模式,因为它更容易使用,因为许多有用的wcf功能依赖于缓冲。使用具有启用的SOAP消息级安全性的流式传输(例如),可能会消除流式传输模式的速度优势(如果您曾经有过)。

在您的情况下,我建议您执行一些解决方法。请检查以下步骤:

  • 尝试使用压缩。它可以大大提高速度和资源使用率,但不能保证您的数据量始终保持不变。谁知道明年您的阵列是否会大100倍?所以你可以在一年之后回到这一点。
  • 替换您的方法返回一个巨型数组,方法只返回一个元素或一小部分元素。然后用一个 GetItemsCountForDownload()调用和适当数量的 GetElementAtIndex(int index)(或< em> GetElementsRange(int startIndex,int endIndex))。无论如何,在这一点上你必须在消息大小(每个呼叫)和执行的呼叫数之间找到一些平衡。
  • 如果您的数据不能轻易地分成小部分(例如,数组的第一个元素是10kb,第二个是15kb,第三个是338mb),那么尝试将两个方法组合在一起:将阵列序列化到磁盘,压缩它将碎裂分成若干可接受尺寸的部分,然后一个接一个地进行转移。
  • 尝试使算法参数可调。将它们放在配置文件中,这样就可以根据可用资源调整每台部署机器上的拆分过程和压缩级别。
  • 通过块容易分割数据和下载块的另一个好处是构建一些错误处理层。如果连接不稳定并且由于某种原因转移失败,您可以尝试仅重新下载一个chuk而不是所有数据。

有关架构的一些提示

  • 找到合适的跨平台压缩算法。绝对可以找到满足您需求的产品。请查看BZip2 for C# <-> PythonGZip for C# <-> Java
  • 尝试让您的架构足够清晰,以供其他程序员使用。您可以为压缩数据传输和未压缩( GetElementsRange GetElementsRangeGZip GetElementsRangeBZip2 )制作不同的方法。或者你可以使用压缩类型参数( GetElementsRange(int startIndex,int endIndex,string compressionType )创建一个方法。无论如何,其他程序员必须能够理解他正在接收什么数据以及如何控制压缩模式。
  • 您可以将数据拆分参数从配置文件移动到方法定义,这样客户端就可以自己定义。
  • 您可以进一步实施两步架构。第一步:远程客户端定义请求的参数(所有这些参数,包括压缩模式,分裂模式和所有其他)。第二步:接收数据。令牌怎么样?方法应如下所示:

    string GetTokenForDataRequest(string compressionMode, int maxChunkSize); //additional parameters like dates range, account number an other are defined in this method only
    int GetChunkCount(string token);
    byte[] GetDataChunkAtIndex(string token, int index);
    

此处 compressionMode 可以是“None”,“BZip2”或“GZip”;如果 maxChunkSize 为0则禁用拆分(所有数据将在一个块中发送),否则将数据拆分为大小等于 maxChunkSize 的块(最后一个将小于其他)。所以近似情况如下:

  1. 远程客户端使用所需参数发送数据请求。
  2. 您生成会话ID(令牌),保存此会话的参数并根据参数准备数据。 “准备数据”是指根据请求加载数据,创建临时文件夹,序列化数据,创建块文件和持久路径以供进一步使用。
  3. 客户端收到一个令牌,该令牌用于检索数据的所有其他方法。
  4. 每次远程客户端通过您的方法请求数据块时,您都会知道它存储在硬盘上的位置,剩余的块数等等 - 这要归功于提供的令牌和持久信息。
  5. 您可以轻松地同时处理多个客户端的同步数据传输会话(只需将数据块存储在不同的临时文件和文件夹中)
  6. 客户端可以重新下载任何块,您无需从数据库(或任何来源)加载数据。
  7. 传输完成后,您可以擦除临时数据并释放一些资源。
  8. 不要只看可能的解决方案。只需谷歌一点点,你就会找到自己解决问题的方法!

答案 1 :(得分:0)

您可以使用streaming邮件传输,但它有一些限制 如果流式传输不适合您,您可以实现数据分页(或尝试现有的实现,如WCF Data Services)。