You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2026/09/28 16:10:53 UTC
(httpcomponents-client) branch master updated: Removed the initial implementation of #evictIdleConnections in H2AsyncClientBuilder as it can cause premature termination of connections with multiplexing message exchanges; added #evictExpiredConnections to proactively evict expired connections from the connection pool
This is an automated email from the ASF dual-hosted git repository.
ok2c pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git
The following commit(s) were added to refs/heads/master by this push:
new 8b64f5991 Removed the initial implementation of #evictIdleConnections in H2AsyncClientBuilder as it can cause premature termination of connections with multiplexing message exchanges; added #evictExpiredConnections to proactively evict expired connections from the connection pool
8b64f5991 is described below
commit 8b64f599175165c91367a92b5e79640d5eda83c0
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Mon Sep 28 17:59:50 2026 +0200
Removed the initial implementation of #evictIdleConnections in H2AsyncClientBuilder as it can cause premature termination of connections with multiplexing message exchanges; added #evictExpiredConnections to proactively evict expired connections from the connection pool
---
.../http/impl/async/H2AsyncClientBuilder.java | 61 ++++++++++++----------
.../http/impl/async/InternalH2ConnPool.java | 6 ++-
2 files changed, 37 insertions(+), 30 deletions(-)
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
index c439bc89c..ed52ed54d 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
@@ -197,8 +197,7 @@ private ExecInterceptorEntry(
private Collection<? extends Header> defaultHeaders;
private RequestConfig defaultRequestConfig;
private Resolver<HttpHost, ConnectionConfig> connectionConfigResolver;
- private boolean evictIdleConnections;
- private TimeValue maxIdleTime;
+ private boolean evictExpiredConnections;
private boolean automaticRetriesDisabled;
private boolean redirectHandlingDisabled;
@@ -212,7 +211,6 @@ private ExecInterceptorEntry(
private List<Closeable> closeables;
-
private Callback<Exception> ioReactorExceptionCallback;
private Decorator<IOSession> ioSessionDecorator;
@@ -718,33 +716,39 @@ public final H2AsyncClientBuilder disableAuthCaching() {
}
/**
- * Makes this instance of HttpClient proactively evict idle connections from the
- * connection pool using a background thread.
- * <p>
- * One MUST explicitly close HttpClient with {@link CloseableHttpAsyncClient#close()}
- * in order to stop and release the background thread.
- * </p>
- * <p>
- * Please note this method has no effect if the instance of HttpClient is configured to
- * use a shared connection manager.
- * </p>
+ * This method has no effect. Its initial implementation has been removed, as it can
+ * cause premature termination of sessions with multiplexing message exchanges.
*
- * @param maxIdleTime maximum time persistent connections can stay idle while kept alive
- * in the connection pool. Connections whose inactivity period exceeds this value will
- * get closed and evicted from the pool.
+ * @deprecated This method has no effect as of version 5.7 and should not be used.
+ * Use {{@link ConnectionConfig#getSocketTimeout()}} to ensure idle connections time out
+ * and get gracefully terminated. Use {@link #evictExpiredConnections()} to proactively
+ * evict expired (closed) connections if required.
*
- * @return this instance.
- * @deprecated Configure connection keep-alive settings appropriately and use
- * {@link #evictExpiredConnections()} instead.
- * @see RequestConfig#getConnectionKeepAlive()
+ * @see ConnectionConfig#getSocketTimeout()
*/
@Deprecated
public final H2AsyncClientBuilder evictIdleConnections(final TimeValue maxIdleTime) {
- this.evictIdleConnections = true;
- this.maxIdleTime = maxIdleTime;
return this;
}
+ /**
+ * Makes this instance of HttpClient proactively evict expired connections from the
+ * connection pool using a background thread.
+ * <p>
+ * Use {{@link ConnectionConfig#getSocketTimeout()}} to ensure idle connections time out
+ * and get gracefully terminated.
+ * <p>
+ * One MUST explicitly close HttpClient with {@link CloseableHttpAsyncClient#close()} in order
+ * to stop and release the background thread.
+ *
+ * @return this instance.
+ *
+ * @since 5.7
+ */
+ public final H2AsyncClientBuilder evictExpiredConnections() {
+ this.evictExpiredConnections = true;
+ return this;
+ }
/**
* Request exec chain customization and extension.
@@ -982,9 +986,8 @@ public CloseableHttpAsyncClient build() {
if (closeablesCopy == null) {
closeablesCopy = new ArrayList<>(1);
}
- if (evictIdleConnections) {
- final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(connPool,
- maxIdleTime != null ? maxIdleTime : TimeValue.ofSeconds(30L));
+ if (evictExpiredConnections) {
+ final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(connPool);
closeablesCopy.add(connectionEvictor::shutdown);
connectionEvictor.start();
}
@@ -1008,16 +1011,18 @@ public CloseableHttpAsyncClient build() {
}
+ private static final TimeValue ONE_MINUTE = TimeValue.ofMinutes(1L);
+
static class IdleConnectionEvictor implements Closeable {
private final Thread thread;
- public IdleConnectionEvictor(final InternalH2ConnPool connPool, final TimeValue maxIdleTime) {
+ public IdleConnectionEvictor(final InternalH2ConnPool connPool) {
this.thread = new DefaultThreadFactory("idle-connection-evictor", true).newThread(() -> {
try {
while (!Thread.currentThread().isInterrupted()) {
- maxIdleTime.sleep();
- connPool.closeIdle(maxIdleTime);
+ ONE_MINUTE.sleep();
+ connPool.evictExpired();
}
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
index 97c6981ff..b1f3357a5 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
@@ -102,8 +102,10 @@ public void completed(final IOSession ioSession) {
});
}
- public void closeIdle(final TimeValue idleTime) {
- sessionPool.closeIdle(idleTime);
+ public void evictExpired() {
+ sessionPool.enumAvailable(e -> {
+ // no op
+ });
}
public void setConnectionConfigResolver(final Resolver<HttpHost, ConnectionConfig> connectionConfigResolver) {