处置时,WCF的ClientBase <tchannel>如何处理TCP连接?

时间:2016-10-15 11:02:30

标签: c# .net wcf sockets tcp

前一段时间我发现了一篇有趣的文章,解释说将HttpClient置于使用块中会在代码执行但不关闭TCP套接字时处理该对象,并且TCP状态最终会转到 TIME_WAIT 并在该州列表中继续进行4分钟的进一步活动(默认)。

所以基本上多次使用这个:

using(var client = new HttpClient())
{
    //do something with http client
}

导致许多开放的TCP连接位于 TIME_WAIT

你可以在这里阅读整篇文章:

You're using HttpClient wrong and it is destabilizing your software

所以我想知道如果我在右键单击项目并选择添加添加服务引用时对Visual Studio创建的ClientBase<TChannel>派生服务类执行相同操作会发生什么。 。并实施了这个:

    //SomeServiceOutThere inherits from ClientBase
    using (var service = new SomeServiceOutThere()) 
    {
       var serviceRequestParameter = txtInputBox.Text;
       var result = service.BaddaBingMethod(serviceRequestParameter);
       //do some magic (see Fred Brooks quote)
    }

但是,我还没有能够重现完全相同的行为,我想知道为什么。

  1. 我创建了一个小型桌面应用,并添加了对IIS托管的WCF服务的引用。
  2. 接下来,我添加了一个按钮,它基本上通过使用代码块调用代码,如上所示。
  3. 第一次点击服务后,我为IP运行netsat,这就是结果:
  4. enter image description here

    1. 到目前为止一切顺利。我再次点击了按钮,确定已建立新连接,而第一个进入 TIME_WAIT 状态:
    2. enter image description here

      1. 但是,在此之后,每次我点击服务时,它都会使用 ESTABLISHED 连接,而不再像HttpClient演示中那样打开(即使将不同的参数传递给服务,但保持应用程序运行。)
      2. WCF似乎很聪明,意识到已经建立了与服务器的连接,并使用它。

        有趣的是,当我重复上述过程,但在每次调用服务之间停止并重新启动应用程序时,我确实得到了与HttpClient相同的行为:

        enter image description here

        ClientBase还存在其他一些潜在问题(例如see here),而且我知道如果服务流量相对较低或者服务器是临时打开的套接字可能根本不是问题设置了大量的最大连接,但我仍然希望能够可靠地测试这是否是一个问题,以及在什么条件下(例如运行Windows服务命中WCF服务而不是桌面应用程序)。

        有什么想法吗?

1 个答案:

答案 0 :(得分:3)

WCF内部不使用HttpClient。 WCF可能使用HttpWebRequest,因为该API当时可用,并且它可能会快一点,因为HttpClient是它的包装。

WCF适用于高性能用例,因此它们确保重用HTTP连接。在我看来,默认情况下不重用连接是不可接受的。这可能是HttpClient的错误或设计问题。

4.6.2 Desktop .NET Framework在HttpClienthandler.Dispose中包含此行:

ServicePointManager.CloseConnectionGroups(this.connectionGroupName);

由于此代码不在CoreClr中,因此没有相关文档。我不知道为什么会这样添加。由于ctor中的this.connectionGroupName = RuntimeHelpers.GetHashCode(this).ToString(NumberFormatInfo.InvariantInfo);,它甚至有一个bug。两个connectionGroupName可能会发生冲突。这是获取应该是唯一的随机数的可怕方法。

如果重新启动该过程,则无法重用现有连接。这就是为什么你看到TIME_WAIT状态的旧连接的原因。这两个过程是无关的。对于他们(和操作系统)中的代码知道他们没有以任何方式合作。跨进程重新启动也很难保存TCP连接(但可能)。我所知道的应用程序没有这样做。

您是否经常启动流程以致这可能成为一个问题?不太可能,但如果是,您可以应用一种常规解决方法,例如减少TIME_WAIT持续时间。

复制这个很容易:只需在循环中启动100k测试过程。