用于活动连接的 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 秒。
我运行的测试如下:
我使用以下 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;
};
}
我在我的应用程序上创建了一个端点,它使用 HttpClient 向 DNS 后面的 URL 发出 GET 请求。
我编写了一个程序,每 1 秒命中一次该端点。
我更改了 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 持续时间过去后尚未使用的连接。
在带有 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 秒。
我运行的测试如下:
我使用以下 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; }; }
我在我的应用程序上创建了一个端点,它使用 HttpClient 向 DNS 后面的 URL 发出 GET 请求。
我编写了一个程序,每 1 秒命中一次该端点。
我更改了 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 持续时间过去后尚未使用的连接。