Skip to content

Commit ee6abef

Browse files
authored
Avoid setting connection request timeout (#30384)
We've been setting this value to 500ms in the default low-level REST client configuration, misunderstanding the effect that it would have. This proved very problematic, as it ends up causing `TimeoutException` returned from the leased pool in some cases even for successful requests. Closes #24069
1 parent 0c6789b commit ee6abef

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

client/rest/src/main/java/org/elasticsearch/client/RestClientBuilder.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public final class RestClientBuilder {
4343
public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000;
4444
public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000;
4545
public static final int DEFAULT_MAX_RETRY_TIMEOUT_MILLIS = DEFAULT_SOCKET_TIMEOUT_MILLIS;
46-
public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT_MILLIS = 500;
4746
public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10;
4847
public static final int DEFAULT_MAX_CONN_TOTAL = 30;
4948

@@ -196,8 +195,7 @@ private CloseableHttpAsyncClient createHttpClient() {
196195
//default timeouts are all infinite
197196
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
198197
.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS)
199-
.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS)
200-
.setConnectionRequestTimeout(DEFAULT_CONNECTION_REQUEST_TIMEOUT_MILLIS);
198+
.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS);
201199
if (requestConfigCallback != null) {
202200
requestConfigBuilder = requestConfigCallback.customizeRequestConfig(requestConfigBuilder);
203201
}

client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,24 @@ private static void assertSetPathPrefixThrows(final String pathPrefix) {
177177
}
178178
}
179179

180+
/**
181+
* This test verifies that we don't change the default value for the connection request timeout as that causes problems.
182+
* See https://github.com/elastic/elasticsearch/issues/24069
183+
*/
184+
public void testDefaultConnectionRequestTimeout() throws IOException {
185+
RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200));
186+
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
187+
@Override
188+
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
189+
RequestConfig requestConfig = requestConfigBuilder.build();
190+
assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), requestConfig.getConnectionRequestTimeout());
191+
//this way we get notified if the default ever changes
192+
assertEquals(-1, requestConfig.getConnectionRequestTimeout());
193+
return requestConfigBuilder;
194+
}
195+
});
196+
try (RestClient restClient = builder.build()) {
197+
assertNotNull(restClient);
198+
}
199+
}
180200
}

client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.http.entity.StringEntity;
3333
import org.apache.http.impl.client.BasicCredentialsProvider;
3434
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
35+
import org.apache.http.nio.entity.NStringEntity;
3536
import org.apache.http.util.EntityUtils;
3637
import org.elasticsearch.mocksocket.MockHttpServer;
3738
import org.junit.AfterClass;
@@ -48,6 +49,9 @@
4849
import java.util.List;
4950
import java.util.Map;
5051
import java.util.Set;
52+
import java.util.concurrent.CopyOnWriteArrayList;
53+
import java.util.concurrent.CountDownLatch;
54+
import java.util.concurrent.TimeUnit;
5155

5256
import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes;
5357
import static org.elasticsearch.client.RestClientTestUtil.getHttpMethods;
@@ -159,6 +163,42 @@ public static void stopHttpServers() throws IOException {
159163
httpServer = null;
160164
}
161165

166+
/**
167+
* Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool)
168+
* See https://github.com/elastic/elasticsearch/issues/24069
169+
*/
170+
public void testManyAsyncRequests() throws Exception {
171+
int iters = randomIntBetween(500, 1000);
172+
final CountDownLatch latch = new CountDownLatch(iters);
173+
final List<Exception> exceptions = new CopyOnWriteArrayList<>();
174+
for (int i = 0; i < iters; i++) {
175+
Request request = new Request("PUT", "/200");
176+
request.setEntity(new NStringEntity("{}", ContentType.APPLICATION_JSON));
177+
restClient.performRequestAsync(request, new ResponseListener() {
178+
@Override
179+
public void onSuccess(Response response) {
180+
latch.countDown();
181+
}
182+
183+
@Override
184+
public void onFailure(Exception exception) {
185+
exceptions.add(exception);
186+
latch.countDown();
187+
}
188+
});
189+
}
190+
191+
assertTrue("timeout waiting for requests to be sent", latch.await(10, TimeUnit.SECONDS));
192+
if (exceptions.isEmpty() == false) {
193+
AssertionError error = new AssertionError("expected no failures but got some. see suppressed for first 10 of ["
194+
+ exceptions.size() + "] failures");
195+
for (Exception exception : exceptions.subList(0, Math.min(10, exceptions.size()))) {
196+
error.addSuppressed(exception);
197+
}
198+
throw error;
199+
}
200+
}
201+
162202
/**
163203
* End to end test for headers. We test it explicitly against a real http client as there are different ways
164204
* to set/add headers to the {@link org.apache.http.client.HttpClient}.

0 commit comments

Comments
 (0)