【问题标题】:Apache HttpClient Keep-Alive Strategy for active connections用于活动连接的 Apache HttpClient Keep-Alive 策略
【发布时间】:2021-08-30 20:36:12
【问题描述】:

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

例如,如果我将 Keep-Alive 策略设置为每个请求返回 5 秒,并且我使用相同的连接每 2 秒访问一次 URL/路由,我的 keep-alive 策略是否会导致此连接离开游泳池?还是会留在池中,因为连接没有空闲?

【问题讨论】:

  • 你没有选择keep-alive作为客户端,是服务器设置了keep-alive标头,Apache HTTP Client的默认实现看这个标头值。
  • @GaëlJ 使用 Apache HttpClient,如果服务器没有向您发送响应,您可以在服务器响应上设置默认的 Keep-Alive 标头。此外,Keep-Alive 标头似乎确实会影响活动和空闲连接(请参阅下面的答案以了解我的调查原因)。

标签: java apache-httpclient-4.x


【解决方案1】:

我刚刚对此进行了测试,并确认 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. 我将本地 DNS 更改为 HttpClient 发送 GET 请求的地址,以指向不会响应请求的虚拟 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 标头,则它假定它与该服务器的连接可以无限期地保持活动状态,并将无限期地保持该连接在它的 PoolingHttpClientConnectionManager 中。

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

【讨论】:

    猜你喜欢
    • 2016-09-07
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多