前一段时间我发现了一篇有趣的文章,解释说将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)
}
但是,我还没有能够重现完全相同的行为,我想知道为什么。
HttpClient
演示中那样打开(即使将不同的参数传递给服务,但保持应用程序运行。)WCF似乎很聪明,意识到已经建立了与服务器的连接,并使用它。
有趣的是,当我重复上述过程,但在每次调用服务之间停止并重新启动应用程序时,我确实得到了与HttpClient
相同的行为:
ClientBase
还存在其他一些潜在问题(例如see here),而且我知道如果服务流量相对较低或者服务器是临时打开的套接字可能根本不是问题设置了大量的最大连接,但我仍然希望能够可靠地测试这是否是一个问题,以及在什么条件下(例如运行Windows服务命中WCF服务而不是桌面应用程序)。
有什么想法吗?
答案 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测试过程。