3434import org .apache .http .client .utils .HttpClientUtils ;
3535import org .apache .http .impl .client .CloseableHttpClient ;
3636import org .apache .http .impl .client .HttpClientBuilder ;
37- import org .apache .http .impl .conn .PoolingHttpClientConnectionManager ;
3837import org .apache .http .protocol .HttpContext ;
3938import org .eclipse .rdf4j .http .client .util .HttpClientBuilders ;
4039import org .slf4j .Logger ;
4645 * @author James Leigh
4746 */
4847public class SharedHttpClientSessionManager implements HttpClientSessionManager , HttpClientDependent {
48+
49+ private static final AtomicLong threadCount = new AtomicLong ();
50+
4951 /**
5052 * Configurable system property {@code org.eclipse.rdf4j.client.executors.corePoolSize} for specifying the
5153 * background executor core thread pool size.
5254 */
5355 public static final String CORE_POOL_SIZE_PROPERTY = "org.eclipse.rdf4j.client.executors.corePoolSize" ;
5456
55- private static final AtomicLong threadCount = new AtomicLong ();
57+ /**
58+ * Configurable system property {@code org.eclipse.rdf4j.client.http.maxConnPerRoute} for specifying the maximum
59+ * number of connections per route (per host). Default is 25.
60+ *
61+ * <p>
62+ * This property determines the maximum number of concurrent connections to a single host (route). Adjusting this
63+ * value can improve performance when communicating with a server that supports multiple concurrent connections.
64+ * </p>
65+ */
66+ public static final String MAX_CONN_PER_ROUTE_PROPERTY = "org.eclipse.rdf4j.client.http.maxConnPerRoute" ;
5667
57- // System property constants for regular timeouts
68+ /**
69+ * Configurable system property {@code org.eclipse.rdf4j.client.http.maxConnTotal} for specifying the maximum total
70+ * number of connections. Default is 50.
71+ *
72+ * <p>
73+ * This property sets the maximum total number of concurrent connections that can be open at the same time.
74+ * Increasing this value allows more simultaneous connections to different hosts, which can improve throughput in
75+ * multi-threaded environments.
76+ * </p>
77+ */
78+ public static final String MAX_CONN_TOTAL_PROPERTY = "org.eclipse.rdf4j.client.http.maxConnTotal" ;
5879
5980 /**
6081 * Configurable system property {@code org.eclipse.rdf4j.client.http.connectionTimeout} for specifying the HTTP
61- * connection timeout in milliseconds for general use. Default is 1 hour .
82+ * connection timeout in milliseconds for general use. Default is 30 seconds .
6283 *
6384 * <p>
6485 * The connection timeout determines the maximum time the client will wait to establish a TCP connection to the
65- * server. A default of 1 hour is set to allow for potential network delays without causing unnecessary timeouts.
86+ * server. A default of 30 seconds is set to allow for potential network delays without causing unnecessary
87+ * timeouts.
6688 * </p>
6789 */
6890 public static final String CONNECTION_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.http.connectionTimeout" ;
6991
7092 /**
7193 * Configurable system property {@code org.eclipse.rdf4j.client.http.connectionRequestTimeout} for specifying the
72- * HTTP connection request timeout in milliseconds for general use. Default is 10 days .
94+ * HTTP connection request timeout in milliseconds for general use. Default is 1 hour .
7395 *
7496 * <p>
75- * The connection request timeout defines how long the client will wait for a connection from the connection pool. A
76- * longer timeout is acceptable here since operations like large file uploads may need to wait for an available
77- * connection.
97+ * The connection request timeout defines how long the client will wait for a connection from the connection pool.
7898 * </p>
7999 */
80100 public static final String CONNECTION_REQUEST_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.http.connectionRequestTimeout" ;
@@ -94,7 +114,7 @@ public class SharedHttpClientSessionManager implements HttpClientSessionManager,
94114
95115 /**
96116 * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.connectionTimeout} for specifying the
97- * HTTP connection timeout in milliseconds when used in SPARQL SERVICE calls. Default is 10 minutes .
117+ * HTTP connection timeout in milliseconds when used in SPARQL SERVICE calls. Default is 5 seconds .
98118 *
99119 * <p>
100120 * A shorter connection timeout is set for SPARQL SERVICE calls to quickly detect unresponsive endpoints in
@@ -105,7 +125,7 @@ public class SharedHttpClientSessionManager implements HttpClientSessionManager,
105125
106126 /**
107127 * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.connectionRequestTimeout} for specifying
108- * the HTTP connection request timeout in milliseconds when used in SPARQL SERVICE calls. Default is 6 hours .
128+ * the HTTP connection request timeout in milliseconds when used in SPARQL SERVICE calls. Default is 10 minutes .
109129 *
110130 * <p>
111131 * This timeout controls how long the client waits for a connection from the pool when making SPARQL SERVICE calls.
@@ -117,7 +137,7 @@ public class SharedHttpClientSessionManager implements HttpClientSessionManager,
117137
118138 /**
119139 * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.socketTimeout} for specifying the HTTP
120- * socket timeout in milliseconds when used in SPARQL SERVICE calls. Default is 6 hours .
140+ * socket timeout in milliseconds when used in SPARQL SERVICE calls. Default is 1 hour .
121141 *
122142 * <p>
123143 * The socket timeout for SPARQL SERVICE calls is set to a shorter duration to detect unresponsive servers during
@@ -126,84 +146,155 @@ public class SharedHttpClientSessionManager implements HttpClientSessionManager,
126146 */
127147 public static final String SPARQL_SOCKET_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.sparql.http.socketTimeout" ;
128148
129- // Default timeout values for general use
149+ // Defaults
150+
151+ /**
152+ * Default core pool size for the executor service. Set to 5.
153+ *
154+ * <p>
155+ * This value determines the number of threads to keep in the pool, even if they are idle. Adjusting this value can
156+ * help manage resource utilization in high-load scenarios.
157+ * </p>
158+ */
159+ public static final int DEFAULT_CORE_POOL_SIZE = 5 ;
160+
161+ /**
162+ * Default maximum number of connections per route (per host). Set to 25.
163+ *
164+ * <p>
165+ * This value limits the number of concurrent connections to a single host. Increasing it can improve performance
166+ * when communicating with a server that can handle multiple connections.
167+ * </p>
168+ */
169+ public static final int DEFAULT_MAX_CONN_PER_ROUTE = 25 ;
170+
171+ /**
172+ * Default maximum total number of connections. Set to 50.
173+ *
174+ * <p>
175+ * This value limits the total number of concurrent connections that can be open at the same time. Increasing it
176+ * allows for more simultaneous connections to different hosts.
177+ * </p>
178+ */
179+ public static final int DEFAULT_MAX_CONN_TOTAL = 50 ;
130180
131181 /**
132- * Default HTTP connection timeout in milliseconds for general use. Set to 1 hour.
182+ * Default HTTP connection timeout in milliseconds for general use. Set to 30 seconds.
183+ *
184+ * <p>
185+ * The connection timeout determines the maximum time the client will wait to establish a TCP connection to the
186+ * server.
187+ * </p>
133188 */
134- public static final int DEFAULT_CONNECTION_TIMEOUT = 60 * 60 * 1000 ; // 1 hour
189+ public static final int DEFAULT_CONNECTION_TIMEOUT = 30 * 1000 ; // 30 seconds
135190
136191 /**
137- * Default HTTP connection request timeout in milliseconds for general use. Set to 10 days.
192+ * Default HTTP connection request timeout in milliseconds for general use. Set to 1 hour.
193+ *
194+ * <p>
195+ * The connection request timeout defines how long the client will wait for a connection from the connection pool.
196+ * </p>
138197 */
139- public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 10 * 24 * 60 * 60 * 1000 ; // 10 days
198+ public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 60 * 60 * 1000 ; // 1 hour
140199
141200 /**
142201 * Default HTTP socket timeout in milliseconds for general use. Set to 10 days.
202+ *
203+ * <p>
204+ * The socket timeout controls the maximum period of inactivity between data packets during data transfer. A longer
205+ * timeout is appropriate for large data transfers.
206+ * </p>
143207 */
144208 public static final int DEFAULT_SOCKET_TIMEOUT = 10 * 24 * 60 * 60 * 1000 ; // 10 days
145209
146210 // Default timeout values for SPARQL SERVICE calls
147211
148212 /**
149- * Default HTTP connection timeout in milliseconds for SPARQL SERVICE calls. Set to 10 minutes.
213+ * Default HTTP connection timeout in milliseconds for SPARQL SERVICE calls. Set to 5 seconds.
214+ *
215+ * <p>
216+ * A shorter connection timeout is set for SPARQL SERVICE calls to quickly detect unresponsive endpoints in
217+ * federated queries.
218+ * </p>
219+ */
220+ public static final int DEFAULT_SPARQL_CONNECTION_TIMEOUT = 5 * 1000 ; // 5 seconds
221+
222+ /**
223+ * Default HTTP connection request timeout in milliseconds for SPARQL SERVICE calls. Set to 10 minutes.
224+ *
225+ * <p>
226+ * This timeout controls how long the client waits for a connection from the pool when making SPARQL SERVICE calls.
227+ * </p>
228+ */
229+ public static final int DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT = 10 * 60 * 1000 ; // 10 minutes
230+
231+ /**
232+ * Default HTTP socket timeout in milliseconds for SPARQL SERVICE calls. Set to 1 hour.
233+ *
234+ * <p>
235+ * The socket timeout for SPARQL SERVICE calls is set to a shorter duration to detect unresponsive servers during
236+ * data transfer.
237+ * </p>
150238 */
151- public static final int DEFAULT_SPARQL_CONNECTION_TIMEOUT = 10 * 60 * 1000 ; // 10 minutes
239+ public static final int DEFAULT_SPARQL_SOCKET_TIMEOUT = 60 * 60 * 1000 ; // 1 hour
240+
241+ // Values as read from system properties or defaults
152242
153243 /**
154- * Default HTTP connection request timeout in milliseconds for SPARQL SERVICE calls. Set to 6 hours .
244+ * Core pool size for the executor service, as read from system properties or defaults .
155245 */
156- public static final int DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT = 6 * 60 * 60 * 1000 ; // 6 hours
246+ public static final int CORE_POOL_SIZE = Integer
247+ .parseInt (System .getProperty (CORE_POOL_SIZE_PROPERTY , String .valueOf (DEFAULT_CORE_POOL_SIZE )));
157248
158249 /**
159- * Default HTTP socket timeout in milliseconds for SPARQL SERVICE calls. Set to 6 hours .
250+ * Maximum number of connections per route (per host), as read from system properties or defaults .
160251 */
161- public static final int DEFAULT_SPARQL_SOCKET_TIMEOUT = 6 * 60 * 60 * 1000 ; // 6 hours
252+ public static final int MAX_CONN_PER_ROUTE = Integer
253+ .parseInt (System .getProperty (MAX_CONN_PER_ROUTE_PROPERTY , String .valueOf (DEFAULT_MAX_CONN_PER_ROUTE )));
162254
163- // Timeout values as read from system properties or defaults
255+ /**
256+ * Maximum total number of connections, as read from system properties or defaults.
257+ */
258+ public static final int MAX_CONN_TOTAL = Integer
259+ .parseInt (System .getProperty (MAX_CONN_TOTAL_PROPERTY , String .valueOf (DEFAULT_MAX_CONN_TOTAL )));
164260
165261 /**
166262 * HTTP connection timeout in milliseconds for general use.
167263 */
168264 public static final int CONNECTION_TIMEOUT = Integer .parseInt (
169- System .getProperty (CONNECTION_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_CONNECTION_TIMEOUT ))
170- );
265+ System .getProperty (CONNECTION_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_CONNECTION_TIMEOUT )));
171266
172267 /**
173268 * HTTP connection request timeout in milliseconds for general use.
174269 */
175270 public static final int CONNECTION_REQUEST_TIMEOUT = Integer .parseInt (
176- System .getProperty (CONNECTION_REQUEST_TIMEOUT_PROPERTY , String . valueOf ( DEFAULT_CONNECTION_REQUEST_TIMEOUT ))
177- );
271+ System .getProperty (CONNECTION_REQUEST_TIMEOUT_PROPERTY ,
272+ String . valueOf ( DEFAULT_CONNECTION_REQUEST_TIMEOUT )) );
178273
179274 /**
180275 * HTTP socket timeout in milliseconds for general use.
181276 */
182- public static final int SOCKET_TIMEOUT = Integer .parseInt (
183- System .getProperty (SOCKET_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SOCKET_TIMEOUT ))
184- );
277+ public static final int SOCKET_TIMEOUT = Integer
278+ .parseInt (System .getProperty (SOCKET_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SOCKET_TIMEOUT )));
185279
186280 /**
187281 * HTTP connection timeout in milliseconds for SPARQL SERVICE calls.
188282 */
189283 public static final int SPARQL_CONNECTION_TIMEOUT = Integer .parseInt (
190- System .getProperty (SPARQL_CONNECTION_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SPARQL_CONNECTION_TIMEOUT ))
191- );
284+ System .getProperty (SPARQL_CONNECTION_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SPARQL_CONNECTION_TIMEOUT )));
192285
193286 /**
194287 * HTTP connection request timeout in milliseconds for SPARQL SERVICE calls.
195288 */
196289 public static final int SPARQL_CONNECTION_REQUEST_TIMEOUT = Integer .parseInt (
197290 System .getProperty (SPARQL_CONNECTION_REQUEST_TIMEOUT_PROPERTY ,
198- String .valueOf (DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT ))
199- );
291+ String .valueOf (DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT )));
200292
201293 /**
202294 * HTTP socket timeout in milliseconds for SPARQL SERVICE calls.
203295 */
204296 public static final int SPARQL_SOCKET_TIMEOUT = Integer .parseInt (
205- System .getProperty (SPARQL_SOCKET_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SPARQL_SOCKET_TIMEOUT ))
206- );
297+ System .getProperty (SPARQL_SOCKET_TIMEOUT_PROPERTY , String .valueOf (DEFAULT_SPARQL_SOCKET_TIMEOUT )));
207298
208299 // Variables for the currently used timeouts
209300
@@ -214,12 +305,12 @@ public class SharedHttpClientSessionManager implements HttpClientSessionManager,
214305 private final Logger logger = LoggerFactory .getLogger (SharedHttpClientSessionManager .class );
215306
216307 /**
217- * independent life cycle
308+ * Independent life cycle
218309 */
219310 private volatile HttpClient httpClient ;
220311
221312 /**
222- * dependent life cycle
313+ * Dependent life cycle
223314 */
224315 private volatile CloseableHttpClient dependentClient ;
225316
@@ -275,7 +366,7 @@ private static class ServiceUnavailableRetryHandler implements ServiceUnavailabl
275366
276367 @ Override
277368 public boolean retryRequest (HttpResponse response , int executionCount , HttpContext context ) {
278- // only retry on ` 408`
369+ // only retry on HTTP 408 (Request Timeout)
279370 if (response .getStatusLine ().getStatusCode () != HttpURLConnection .HTTP_CLIENT_TIMEOUT ) {
280371 return false ;
281372 }
@@ -287,11 +378,10 @@ public boolean retryRequest(HttpResponse response, int executionCount, HttpConte
287378 return false ;
288379 }
289380
290- // worst case, the connection pool is filled to the max and all of them idled out on the server already
291- // we then need to clean up the pool and finally retry with a fresh connection. Hence, we need at most
292- // pooledConnections+1 retries.
293- // the pool size setting used here is taken from `HttpClientBuilder` when `useSystemProperties()` is used
294- int pooledConnections = Integer .parseInt (System .getProperty ("http.maxConnections" , "5" ));
381+ // Worst case, the connection pool is filled to the max and all of them idled out on the server already
382+ // We then need to clean up the pool and retry with a fresh connection. Hence, we need at most
383+ // pooledConnections + 1 retries.
384+ int pooledConnections = MAX_CONN_PER_ROUTE ;
295385 if (executionCount > (pooledConnections + 1 )) {
296386 return false ;
297387 }
@@ -332,7 +422,7 @@ public SharedHttpClientSessionManager() {
332422 return thread ;
333423 });
334424
335- Integer corePoolSize = Integer . getInteger ( CORE_POOL_SIZE_PROPERTY , 1 ) ;
425+ Integer corePoolSize = CORE_POOL_SIZE ;
336426 ((ThreadPoolExecutor ) threadPoolExecutor ).setCorePoolSize (corePoolSize );
337427 this .executor = threadPoolExecutor ;
338428 }
@@ -486,6 +576,8 @@ private CloseableHttpClient createHttpClient() {
486576 .evictIdleConnections (30 , TimeUnit .MINUTES )
487577 .setRetryHandler (retryHandlerStale )
488578 .setServiceUnavailableRetryStrategy (serviceUnavailableRetryHandler )
579+ .setMaxConnPerRoute (MAX_CONN_PER_ROUTE )
580+ .setMaxConnTotal (MAX_CONN_TOTAL )
489581 .useSystemProperties ()
490582 .setDefaultRequestConfig (requestConfig )
491583 .build ();
0 commit comments