关闭所有底层网络连接

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

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

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

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

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

问题是:
我如何杀死服务器的所有底层连接以强制重新连接?

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

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

有两种方法可以让.Net发布这些连接。 它们都涉及到ServicePoint级别并处理连接组。

  1. CloseConnectionGroups

    创建HTTPWebRequest时,可以为其指定连接组。 从那里,您可以使用ServicePoint中的CloseConnectionGroup()函数来终止与该服务的所有连接。

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

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

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

  2. ReleaseAllConnectionGroups

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

      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标志。

为什么不使用以下代码:

SqlConnection.ClearAllPools();

我在我的所有应用中使用它。