10

背景:
我有一些代码连接到服务器以提取数据。但是,在某些时候,程序进入了无法连接到服务器的状态。我们看到的问题是,当我们尝试重新连接时,服务器不断超时。

插件:
我们将超时设置为网络插件(Thrift 插件)使用的默认值。这些值是 100k 毫秒超时和 300k 毫秒读写超时。不完全是短暂的超时。此外,每次尝试重新连接时,我们都会重新创建插件的类,因此每次尝试重新连接时都会重置其内部设置的任何值。我相信超时不是问题。而且我相信插件不是问题。

网络:
我们看到这些重复的超时发生了半个小时。当我们重新启动服务(不是机器)时,它立即恢复在线。所以,我知道这不是网络问题。这让我相信这是我们代码中的某些东西进入了无效的网络状态。此外,这是一种我们无法控制的状态,因为我们的插件对我们隐藏了所有好的网络内容——包括超时、keepalive 标志和连接组(以及其他)。我们基本上无权访问 HTTPWebReqest 成员。

问题:
当我们的网络设置进入此状态时,我们会尝试关闭所有连接并重新连接到服务器。目标是终止所有活动连接,以重置我们进入的任何状态。但是,当我们尝试重新连接时,我们的重新连接会超时。

不知何故(可能是由于我们无法控制的 KeepAlive 和 TCP 流水线),即使我们关闭了所有连接,网络连接仍然保持打开状态。这使我们处于糟糕的状态,并阻止我们循环连接到服务器。

问题:
如何终止与服务器的所有底层连接以强制重新连接?

4

2 回答 2

10

底层 .Net 架构将保持连接(通过 KeepAlive)以提高整体网络性能。最简单的解决方案是在所有连接上将 KeepAlive 设置为 false,这样它们就不会保持那些无效状态。缺点是您会增加流量,因为他们每次都必须重新建立连接。

此外,由于您无权访问 keepalive(或 HTTPWebRequest 对象),因此您必须找到一种方法来终止请求设置之外的连接。

有两种方法可以让 .Net 释放这些连接。它们都涉及到服务点级别和处理连接组。

  1. 关闭连接组

    当你创建你的 HTTPWebRequest 时,你可以给它一个连接组。从那里,您可以使用 ServicePoint 中的 CloseConnectionGroup() 函数来终止与该服务的所有连接。

    ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
    srvrPoint.CloseConnectionGroup(myConnGroup)
    

    当然,如果您有多个连接组,则需要为每个连接组循环执行此操作。

    请注意,如果您选择此路径,请注意不要将所有连接放在同一个组中。这可能会导致您的套接字用完。 更多信息在这里

  2. 释放所有连接组

    ServicePoint 类中有一个内部函数,您可以调用它来终止与给定服务点(即服务器)的所有连接。但是,因为它是类内部的,所以您必须使用反射来获得它:

        ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
        MethodInfo ReleaseConns = srvrPoint.GetType().GetMethod
                ("ReleaseAllConnectionGroups",
                BindingFlags.Instance | BindingFlags.NonPublic);
        ReleaseConns.Invoke(srvrPoint, null);
    

    此代码只是从该 ServerPoint 中提取 ReleaseAllConnectionGroups 并在没有参数的情况下调用它。此函数将遍历其内部列表中的所有连接组并释放所有这些资源——终止所有连接。

    失败:因为这是一个私人成员,所以如果你升级你的 .Net 版本,你不能保证它会在那里。不过,它目前在 2.0 到 4.5 版本中可用。ReleaseAllConnectionGroups 的反向工程代码的链接。

因为您无法设置连接组,所以您必须使用选项 2。

不幸的是,没有其他方法可以让 .Net 在不设置 KeepAlive 标志的情况下关闭这些低级连接并释放它们的 KeepAlive 状态。

于 2013-08-22T12:20:05.123 回答
-4

为什么不使用以下代码:

SqlConnection.ClearAllPools();

我在所有应用程序中都使用它。

于 2013-11-20T15:02:22.947 回答