gpt4 book ai didi

c# - WCF 的 ClientBase 在 Disposed 时如何处理 TCP 连接?

转载 作者:可可西里 更新时间:2023-11-01 02:32:51 43 4
gpt4 key购买 nike

前一段时间我看到一篇有趣的文章,解释了将 HttpClient在 using block 中将在代码执行但不关闭 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

所以我想知道如果我对 ClientBase<TChannel> 做同样的事情会发生什么当您右键单击项目并选择添加 添加服务引用时,由 Visual Studio 创建的派生服务类。 . 并实现了这个:

    //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. 接下来,我添加了一个按钮,基本上通过上面显示的 using 代码块调用代码。
  3. 第一次访问该服务后,我为 IP 运行 netsat,结果如下:

enter image description here

  1. 到目前为止一切顺利。我再次点击按钮,果然,新的连接建立了,而第一个连接进入了TIME_WAIT状态:

enter image description here

  1. 但是,在此之后,每次我访问该服务时,它都会使用ESTABLISHED 连接,并且不再像HttpClient 中那样打开。演示(即使将不同的参数传递给服务,但保持应用程序运行)。

似乎 WCF 足够聪明,可以意识到已经建立了与服务器的连接,并使用它。

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

enter image description here

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

有什么想法吗?

最佳答案

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

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

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

ServicePointManager.CloseConnectionGroups(this.connectionGroupName);

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

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

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

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

关于c# - WCF 的 ClientBase<TChannel> 在 Disposed 时如何处理 TCP 连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40058217/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com