用于活动连接的 Apache HttpClient Keep-Alive 策略

Apache HttpClient Keep-Alive Strategy for active connections

在带有 PoolingHttpClientConnectionManager 的 Apache HttpClient 中,Keep-Alive strategy 是否会更改活动连接在从连接池中删除之前保持活动状态的时间?还是只会关闭空闲连接?

例如,如果我将每个请求的 Keep-Alive 策略设置为 return 5 秒,并且我使用相同的连接每 2 秒点击一次 URL/route,我的保持活动策略导致此连接离开池?或者它会留在池中,因为连接不空闲吗?

我刚刚对此进行了测试,并确认 Keep-Alive 策略将仅在 Keep-Alive 持续时间过去后才空闲来自 HttpClient 的连接池 的连接。 Keep-Alive 持续时间决定连接是否空闲,事实上 - 如果 Keep-alive 策略说要保持连接活动 10 秒,并且我们每 2 秒收到一次来自服务器的响应,连接将在最后一次成功响应后保持存活 10 秒

我运行的测试如下:

  1. 我使用以下 ConnectionKeepAliveStrategy 设置了 Apache HttpClient(使用 PoolingHttpClientConnectionManager):

        return (httpResponse, httpContext) -> {
            // Honor 'keep-alive' header
            HeaderElementIterator it = new BasicHeaderElementIterator(
                    httpResponse.headerIterator(HTTP.CONN_KEEP_ALIVE));
            while (it.hasNext()) {
                HeaderElement he = it.nextElement();
                String param = he.getName();
                String value = he.getValue();
                if (value != null && param.equalsIgnoreCase("timeout")) {
                    try {
                        return Long.parseLong(value) * 1000;
                    } catch(NumberFormatException ignore) {
                    }
                }
            }
            if (keepAliveDuration <= 0) {
                return -1; // the connection will stay alive indefinitely.
            }
            return keepAliveDuration * 1000;
        };
    }
    
  2. 我在我的应用程序上创建了一个端点,它使用 HttpClient 向 DNS 后面的 URL 发出 GET 请求。

  3. 我编写了一个程序,每 1 秒命中一次该端点。

  4. 我更改了 HttpClient 向其发送 GET 请求的地址的本地 DNS,以指向一个不会响应请求的虚拟 URL。 (这是通过更改我的 /etc/hosts 文件完成的)。

当我将 keepAliveDuration 设置为 -1 秒时,即使在将 DNS 更改为指向虚拟 URL 之后,HttpClient 仍会不断向旧 IP 地址发送请求,尽管 DNS 已更改。我将此测试 运行 保持了 1 小时,它继续向与陈旧 DNS 关联的旧 IP 地址发送请求。这将无限期地发生,因为我的 ConnectionKeepAliveStrategy 已配置为无限期地保持与旧 URL 的连接。

当我将keepAliveDuration设置为10时,我更改了我的DNS后,我连续发送成功的请求,大约一个小时。直到我关闭我的负载测试并等待 10 秒,直到我们收到一个新的连接。这意味着 ConnectionKeepAliveStrategy 在服务器最后一次成功响应.

后 10 秒从 HttpClient 的连接池中删除了连接

结论

默认情况下,如果 HttpClient 没有从服务器收到的响应中收到 Keep-Alive header,它会假定它与该服务器的连接可以无限期地保持活动状态,并将保持该连接无限期地在 PoolingHttpClientConnectionManager 中。

如果您像我一样设置 ConnectionKeepAliveStrategy,那么它将向服务器 的响应中添加一个Keep-Alive header。在 HttpClient 响应上具有 Keep-Alive header 将导致连接在 Keep-Alive 持续时间过去后离开连接池,在服务器最后一次成功响应后。这意味着只有空闲连接会受到 Keep-Alive 持续时间的影响,而“空闲连接”是指在 Keep-Alive 持续时间过去后尚未使用的连接。