自定义 WCF 扩展强制并发作按顺序运行

本文介绍如何遇到客户端超时或长时间延迟期,因为自定义 WCF 扩展强制并发作按顺序运行,并提供解决方法。

原始产品版本: Microsoft .NET Framework 4.5
原始 KB 数: 2907010

现象

假设出现了下面这种情景:

  • 你已将 Windows Communication Foundation (WCF) 服务配置为处理多个并发请求。

  • 你有以下任一 WCF 扩展的自定义实现:

    • ServiceAuthenticationManager
    • ServiceAuthorizationManager
    • IDispatchMessageInspector
    • IDispatchOperationSelector
  • 这些实现的计算成本很高,或者它们偶尔会产生较长的延迟期。

  • 并发服务作似乎按顺序运行,或者客户端超时。

如果遇到与服务器负载无关的客户端超时或长时间的响应时间,则可以以触发此问题的方式使用这些自定义 WCF 扩展。

此外,可能会遇到一种情况,其中一个请求会延迟其他请求。 然后,许多请求可能会突然完成,然后另一个请求再次延迟其他请求。 可以使用 性能监视器 中的“每秒调用数”计数器来查看此行为ServiceModelService。 发生此行为时,在扩展代码运行时,计数可能会下降到零,即使多个并发请求未完成也是如此。 当扩展代码将控制权返回到 WCF 时,计数器将返回到其典型级别,直到扩展代码的下一个延迟再次将其降至零。

原因

出现此问题的原因是 WCF 在消息处理管道中以同步方式调用这些特定的扩展点。 这些扩展点中的延迟可能会阻止该管道。 这可以防止并发执行服务作。 在此期间接收的消息将排队,但直到这些扩展点返回到 WCF 后才会提供服务。

这会导致服务作一次运行一次,而不是同时运行。 每个请求都会排队等待上一个请求完成这些扩展点的执行。 如果延迟足够高,则最新请求在等待早期请求完成时可能会超时。

下面是受影响的特定扩展性方法:

  • Microsoft .NET Framework 4.5 和 .NET Framework 4.0:
    • ServiceAuthenticationManager.Authenticate()
  • .NET Framework .NET Framework 4.5、.NET Framework 4.0、.NET Framework 3.5 和 .NET Framework 3.0:
    • ServiceAuthorizationManager.CheckAccessCore()
    • IDispatchMessageFormatter.AfterReceiveRequest()
    • IDispatchOperationSelector.SelectOperation()

解决方法

若要解决此问题,请使用以下方法之一:

  • 最大程度地减少这些扩展点的延迟。
  • 在管道中的其他位置移动高延迟开销。
  • 使用不同的 WCF 绑定。

有一些常见做法可能会导致这些扩展点出现高延迟:

  • 访问数据库,尤其是在另一层上
  • 在另一层调用其他服务
  • 使用大量内存或线程
  • 执行计算成本高昂的工作

如果需要此高延迟工作,则应将其移出这些扩展点。 例如,如果在服务作本身内执行此工作,它将允许多个作同时运行。

此行为还可能取决于用于终结点的绑定的功能。 例如, BasicHttpBinding 展示此行为,而 WsHttpBinding 不会显示此行为。

参考