为啥 WCF 不支持服务端超时?

Posted

技术标签:

【中文标题】为啥 WCF 不支持服务端超时?【英文标题】:Why doesn’t WCF support service-side timeouts?为什么 WCF 不支持服务端超时? 【发布时间】:2011-06-25 20:51:12 【问题描述】:

我们最近发现 WCF 不支持服务端的超时操作(注意,service 端,而不是客户端)。虽然客户端在指定时间后断开,但我们的测试表明,对于 netNamedPipeBinding、netTcpBinding 和 basicHttpBinding,我们指定的没有超时将导致服务操作在被调用后停止。以下是我们尝试的具体绑定配置:

<bindings>
  <netNamedPipeBinding>
    <binding name="TestServiceBindingConfigurationNamedPipe"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </netNamedPipeBinding>
  <netTcpBinding>
    <binding name="TestServiceBindingConfigurationTcp"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </netTcpBinding>
  <basicHttpBinding>
    <binding name="TestServiceBindingConfigurationBasicHttp"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </basicHttpBinding>
</bindings>

我们的测试服务实现如下所示:

public class TestServiceImpl : ITestService

    public TestResult TestIt(TestArgs args)
    
        var stopwatch = new Stopwatch();
        stopwatch.Start();

        // this is a contrived example, but it shows that WCF never stops this thread
        while (true)
        
            Console.WriteLine("0> I'm running forever...", stopwatch.Elapsed);
        

        return new TestResult Result = "Args were " + args.Args;
    

使用 netNamedPipeBinding 和 netTcpBinding,我们的客户端应用会在 5 秒后超时,但服务会无限期地继续运行。

这带来了我的问题——这是一个错误吗?如果服务运行时间超过预期,WCF 是否不想让服务超时?

在我看来,与此相关的一些潜在负面问题包括:

    服务实例的默认限制是10个。因此,如果您的服务中有坏代码永远运行并且被命中10次,您的服务将完全关闭;不接受新的连接。 对于服务永远运行这一事实没有任何可见性 - 缺少自定义日志记录或可能使用性能计数器 如果没有其他机制使操作超时,则服务调用正在使用的任何资源(例如 SQL 行、页和表锁)都可能被无限期保留。

【问题讨论】:

【参考方案1】:

怎么样:

<system.web>
    <httpRuntime executionTimeout="inSeconds"/>
</system.web>

【讨论】:

That also no longer works beginning with .NET 3.0 SP1 and later【参考方案2】:

我自己也注意到了这个问题......我想不出一个很好的理由为什么他们不会将服务端操作超时作为平台的一部分。

【讨论】:

【参考方案3】:

如果您有永远运行的错误代码,超时可能只会让事情变得更糟。 尽可能修复错误代码!请参阅 Eric Lippert 的文章 Careful with that axe,了解这些情况。

如果这是在开发中,您可能想尝试在您的服务实现中设置一个调用serviceCallThread.Abort()System.Threading.Timer。但是,请确保您在返回之前彻底解除了计时器 - 这种方法极易出错,由于并发问题的混合,不拥有服务调用到达的线程, ThreadAbortException 的古怪行为,以及 Eric 解释的关于盲目终止已经消失的代码的问题。

【讨论】:

我们想要的是看到永远运行的坏代码。我们宁愿让它中止并抛出 TimeoutException,也不愿让它在没有可见性的情况下吃掉 CPU,告诉我们有错误的代码需要修复。 是的,我的意思是摆脱运行时间过长的代码是有意义的。但是,如果您不希望它永远运行呢?当所有客户端长时间断开连接时,您如何知道服务仍在执行以及处于什么状态? 关于有一个定时器来中止服务线程,这正是我们最终实现的。我问这个问题的部分原因是因为我真的很不舒服必须自己编写这段代码,因为正如你所说,它“非常容易出错”。我一直希望我错过了某处的配置行!

以上是关于为啥 WCF 不支持服务端超时?的主要内容,如果未能解决你的问题,请参考以下文章

如何限制 WCF 服务的请求执行时间?

服务端增加WCF服务全局异常处理机制

在 WCF 服务 C# 的服务器端获取客户端的 Mac 地址不重复(在 WCF 3.0 中获取客户端 IP 地址)

WCF实现长连接

WCF系列之双工通信

C# 编写WCF简单的服务端与客户端