65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF 4.5 有什么新功能?IIS 托管中的流式处理得到改进

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2012 年 2 月 3 日

CPOL

6分钟阅读

viewsIcon

29914

IIS 托管中的流式传输得到改进。

正如我在上一篇文章中承诺的那样,我将继续致力于向您介绍 WCF 4.5 中的新变化。

这是 WCF 4.5 系列的第九篇文章。本文继续介绍之前关于 Web 托管功能的文章,这一次,我们将讨论 WCF 在 IIS 中托管时流式处理功能的改进。

之前的文章

  1. WCF 4.5 有什么新内容?让我们从 WCF 配置开始
  2. WCF 4.5 有什么新内容?单个 WSDL 文件
  3. WCF 4.5 有什么新内容?配置文件中的工具提示和智能感知
  4. WCF 4.5 有什么新内容?配置验证
  5. WCF 4.5 有什么新内容?IIS 中单个端点支持多种身份验证
  6. WCF 4.5 有什么新内容?IIS 的自动 HTTPS 端点
  7. WCF 4.5 中的新功能? BasicHttpsBinding
  8. WCF 4.5 的新特性?ASP.NET 兼容模式的默认值已更改

如果您曾经尝试过创建使用流式请求的 WCF 服务(例如,文件上传服务)并将其托管在 IIS 中,您可能已经注意到您的 WCF 服务出现了一些奇怪的行为——似乎 WCF 延迟接收请求,就像它已完全加载到内存中,然后才传递给 WCF。那么它是流式的吗?还是实际上是缓冲的?嗯,两者皆是。

当您在 IIS 中托管 WCF 服务时,即使您不使用 ASP.NET 兼容模式,也会附加一些 ASP.NET 管道。这在 MSDN 的WCF 服务和 ASP.NET文章中有详细介绍(查找关于 PostAuthenticateRequest 事件的部分)。在 .NET 4 中,ASP.NET 中存在一个设计缺陷,会导致发送到 WCF 的请求在 ASP.NET 中被缓冲。这种缓冲行为会导致几个主要的副作用。

  1. 从 ASP.NET 接收到流式消息到实际调用 WCF 服务方法之间存在延迟。
  2. 由于缓冲,存在一定的内存消耗——消耗的确切内存量取决于客户端发送的消息的大小,但如果您增加 ASP.NET 的MaxRequestLength、IIS 7 的MaxAllowedContentLength,以及当然还有 WCF 的MaxReceivedMessageSizeMaxBufferSize,内存消耗甚至可能达到数百 MB。
  3. 当 ASP.NET 缓冲请求时,它会同时使用内存和磁盘。ASP.NET 的 requestLengthDiskThreshold配置设置控制何时 ASP.NET 开始使用磁盘。如果您一次上传多个文件到 WCF,由于多个文件同时写入磁盘,您将开始看到一些延迟。顺便说一句,文件被写入 Web 应用程序的临时 ASP.NET 文件夹下的“upload”文件夹(位于 c:\windows\Microsoft.NET\Framework\vX.X.XXXX\Temporary ASP.NET Files\),并在请求处理完成后被删除。

为了展示这种行为,我创建了一个客户端应用程序,该应用程序将一个 500MB 的文件上传到 WCF 服务。WCF 服务托管在 IIS 中,并设置为流式请求(您可以在此处下载 StreamingInIIS 示例解决方案)。以下输出显示了服务接收和处理请求的时间以及消耗的内存的一些信息。

  1. 客户端于 2012/01/17 19:03:25 开始上传
  2. 开始前的可用内存为:2701MB
  3. 客户端于 2012/01/17 19:03:44 完成上传
  4. 完成后的可用内存为:2699MB
  5. ASP.NET 上的可用内存为:2701MB
  6. ASP.NET 于 2012/01/17 19:03:28 收到上传
  7. WCF 上的可用内存为:2122MB
  8. WCF 于 2012/01/17 19:03:38 开始接收文件
  9. WCF 于 2012/01/17 19:03:43 完成接收文件

文件大小为:524288000
按任意键继续 . . .

关于这些结果的一些注意事项

  1. 客户端开始 / 客户端完成(第 1+3 行)– 客户端等待服务的**总时间**为**19 秒**;这包括上传时间、ASP.NET 的缓冲时间以及 WCF 处理接收到的流的时间。
  2. **ASP.NET 在客户端开始发送流的 3 秒后开始接收**流(第 6 行)。
  3. **WCF 在 ASP.NET 开始接收流的 10 秒后开始接收**流,距客户端开始发送流总共**13 秒**(第 8 行)。总而言之,WCF 花了**5 秒**来**从 ASP.NET 读取整个流**(第 8+9 行)。
  4. 在客户端发送消息之前,机器上的**可用内存**为**2701MB**,这也是 ASP.NET 首次收到消息时的可用内存。当 WCF 收到请求并开始处理时,可用内存为**2122MB** – **约 580MB 的内存**被消耗在此操作中(第 2、5 和 7 行)。
  5. 至于生成的临时文件,这是临时 ASP.NET 文件夹内容的屏幕截图

image

注意:为了显示 ASP.NET 的信息,我使用了 ASP.NET 兼容模式。如果您想验证在不使用兼容模式的情况下问题也存在,可以在示例代码中关闭它(查看客户端发送请求的时间与 WCF 实际开始处理请求的时间之间的差异——应该会有很大的延迟)。

所以我们看到 WCF 4 在 IIS 上无法很好地处理流式内容,那么 WCF 4.5 呢?有什么变化?

在 WCF 4.5 中,这种情况就不会发生——使用 .NET 4.5,ASP.NET 不会缓冲请求,而是直接将其转发给 WCF,因此我们不会遇到任何延迟、内存消耗或磁盘使用。

想看看证据吗?我在 Windows Server 8 上使用 IIS 上的 WCF 4.5 运行了相同的演示代码。我使用了较小的文件大小(200MB),因为这是一个内存较少的虚拟机,但您仍然可以清楚地看到差异。

  1. 客户端于 2011/11/27 上午 7:23:18 开始上传
  2. 开始前的可用内存为:942MB
  3. 客户端于 2011/11/27 上午 7:23:46 完成上传
  4. 完成后的可用内存为:942MB
  5. ASP.NET 上的可用内存为:941MB
  6. ASP.NET 于 2011/11/27 上午 7:23:20 收到上传
  7. WCF 上的可用内存为:942MB
  8. WCF 于 2011/11/27 上午 7:23:20 开始接收文件
  9. WCF 于 2011/11/27 上午 7:23:46 完成接收文件

文件大小为:209715200
按任意键继续 . . .

首先要注意的是——内存消耗在整个执行过程中没有变化——**保持在约 942MB 左右**(第 2、4、5、7 行)。

至于延迟——**WCF 收到请求的时间与 ASP.NET 收到请求的时间相同**(第 6+8 行),即**在客户端开始发送请求 2 秒后**。

哦,而且由于 ASP.NET 直接将流传递给了 WCF,**没有创建临时文件**!!

这就是 WCF 4.5 在 IIS 上实现的真正流式处理。

敬请期待更多关于 WCF 4.5 新特性的文章。你也可以在 Twitter 上关注我 (@IdoFlatow),以便在发布新文章时获得更新。

© . All rights reserved.