【问题标题】:How to detect when a WCF client failed to close properly?如何检测 WCF 客户端何时无法正确关闭?
【发布时间】:2015-08-13 22:21:31
【问题描述】:

我正试图找出我们在使用频繁的 WCF 服务之一时遇到的问题。它偶尔会变得无响应,从而使我们依赖该服务的几个内部网站无法使用。

我们怀疑这是因为一个或多个消费网站未能正确关闭连接,因此我们达到了服务允许的并发连接数限制。然而,我们没有实际的方法来确定哪一个,因为跨多个 tfs 存储库有这么多。

简而言之,当客户端在 wcf 代理上调用 Close() 时,如何从服务中检测到?或者更确切地说,如何检测服务方法完成后http连接是否仍然打开?

我在本地工作站上创建了一个测试服务和客户端,并尝试了以下方法,但都没有奏效:

测试服务:

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
}

测试客户端:

class Program
{
    static void Main(string[] args)
    {
        ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
        Console.WriteLine(client.GetData(0));
        Console.ReadKey();
        client.Close();
        Console.WriteLine("Closed.");
        Console.ReadKey();
    }
}

运行 netstat 表明,即使在 client.Close() 之后,连接仍然保持打开状态(也许我只是误解了 netstat 的输出)。

perfmon 性能计数器(在添加 ServiceModelService 4.0.0.0 之后)报告服务调用甚至在 client.Close() 执行之前就已完成。服务调用后,client.Close() 前后的计数器没有变化。

接下来,我尝试监听 OperationContext.Current.Channel.Closed 事件(以及 Closing 和 Faulted):

public class Service1 : IService1
{
    public string GetData(int value)
    {
        OperationContext.Current.Channel.Faulted += Channel_Faulted;
        OperationContext.Current.Channel.Closing += Channel_Closing;
        OperationContext.Current.Channel.Closed += Channel_Closed;
        return string.Format("You entered: {0}", value);
    }

    void Channel_Faulted(object sender, EventArgs e)
    {
        // Breakpoint
    }

    void Channel_Closing(object sender, EventArgs e)
    {
        // Breakpoint
    }

    void Channel_Closed(object sender, EventArgs e)
    {
        // Breakpoint
    }
}

但是我在事件处理程序中放置的断点都没有被命中。

我还尝试在 Global.asax 的 Session_Start 和 Session_End 事件中设置断点。 Session_Start 确实会触发,但 Session_End 永远不会触发(尽管我不知道会话是否与 http 连接是否处于活动状态有关)。

我对 wcf 有点陌生(我之前写过几个非常基本的服务),所以我觉得我在这个问题上有点过头了,深入研究我不理解的部分(例如,我在今天之前不知道 OperationContext 存在)。

【问题讨论】:

  • 你的服务是无状态的还是有状态的?
  • 我们遇到问题的服务是无状态的。
  • 该死的,stackoverflow 已经不是以前的样子了。如果我在 2008 年问过这个问题,到现在我已经有十几个答案了。

标签: c# wcf


【解决方案1】:

您应该在调用服务时处理异常,否则通道可能无法正常关闭。

例如:from here:

    WCFServiceClient c = new WCFServiceClient();

    try
    {
            c.HelloWorld();
    }
    catch
    {
            c.Abort();
            throw;
    }
    finally
    {
            c.Close();
    }

(如果愿意,还有一个使用“使用”的示例)。

也可以看看here

【讨论】:

  • 我发布的只是一个测试客户端。我们的大多数应用程序都应用您所说的模式。但是,.NET 3.5 框架中存在一个错误,代理可以引发一些异常,但仍然在服务端保持连接打开。在这种情况下,在 Abort 之后调用 Close 完全没有用,因为客户端在 Abort() 之后无法与服务器进行任何通信。我们的许多应用都在 3.5 中,由于各种业务原因,无法立即升级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
相关资源
最近更新 更多