aboutsummaryrefslogtreecommitdiffstats
path: root/vespa-feed-client
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2023-05-05 10:44:19 +0200
committerBjørn Christian Seime <bjorncs@yahooinc.com>2023-05-05 10:44:20 +0200
commit005299acdb85b626b8c2fea2677c7f862d7b2fa6 (patch)
tree809ad4acf8398b4fa941ef0a1fb5004c191e0bb3 /vespa-feed-client
parent1d0076c194c06b2306599ac5b68db702a17d9f73 (diff)
Ensure socket timeout is longer than response timeouts
Resolve all deprecation warnings
Diffstat (limited to 'vespa-feed-client')
-rw-r--r--vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java57
1 files changed, 30 insertions, 27 deletions
diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java
index 8e7bf59cd0f..a2c535564b5 100644
--- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java
+++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java
@@ -5,15 +5,16 @@ import ai.vespa.feed.client.FeedClientBuilder.Compression;
import ai.vespa.feed.client.HttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders;
-import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.net.URIAuthority;
@@ -50,7 +51,6 @@ class ApacheCluster implements Cluster {
private final List<BasicHeader> defaultHeaders = Arrays.asList(new BasicHeader(HttpHeaders.USER_AGENT, String.format("vespa-feed-client/%s", Vespa.VERSION)),
new BasicHeader("Vespa-Client-Version", Vespa.VERSION));
private final Header gzipEncodingHeader = new BasicHeader(HttpHeaders.CONTENT_ENCODING, "gzip");
- private final RequestConfig requestConfig;
private final Compression compression;
private int someNumber = 0;
@@ -61,7 +61,6 @@ class ApacheCluster implements Cluster {
for (int i = 0; i < builder.connectionsPerEndpoint; i++)
for (URI endpoint : builder.endpoints)
endpoints.add(new Endpoint(createHttpClient(builder), endpoint));
- this.requestConfig = createRequestConfig(builder);
this.compression = builder.compression;
}
@@ -87,7 +86,11 @@ class ApacheCluster implements Cluster {
request.setScheme(endpoint.url.getScheme());
request.setAuthority(new URIAuthority(endpoint.url.getHost(), portOf(endpoint.url)));
long timeoutMillis = wrapped.timeout() == null ? 190_000 : wrapped.timeout().toMillis() * 11 / 10 + 1_000;
- request.setConfig(RequestConfig.copy(requestConfig).setResponseTimeout(Timeout.ofMilliseconds(timeoutMillis)).build());
+ RequestConfig reqCfg = RequestConfig.custom()
+ .setConnectionRequestTimeout(Timeout.DISABLED)
+ .setResponseTimeout(Timeout.ofMilliseconds(timeoutMillis))
+ .build();
+ request.setConfig(reqCfg);
defaultHeaders.forEach(request::setHeader);
wrapped.headers().forEach((name, value) -> request.setHeader(name, value.get()));
if (wrapped.body() != null) {
@@ -160,7 +163,6 @@ class ApacheCluster implements Cluster {
}
- @SuppressWarnings("deprecation")
private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilderImpl builder) throws IOException {
SSLContext sslContext = builder.constructSslContext();
String[] allowedCiphers = excludeH2Blacklisted(excludeWeak(sslContext.getSupportedSSLParameters().getCipherSuites()));
@@ -168,24 +170,34 @@ class ApacheCluster implements Cluster {
throw new IllegalStateException("No adequate SSL cipher suites supported by the JVM");
ClientTlsStrategyBuilder tlsStrategyBuilder = ClientTlsStrategyBuilder.create()
- .setTlsDetailsFactory(TlsDetailsFactory::create)
.setCiphers(allowedCiphers)
.setSslContext(sslContext);
if (builder.hostnameVerifier != null)
tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier);
- return HttpAsyncClients.createHttp2Minimal(H2Config.custom()
- .setMaxConcurrentStreams(builder.maxStreamsPerConnection)
- .setCompressionEnabled(true)
- .setPushEnabled(false)
- .setInitialWindowSize(Integer.MAX_VALUE)
- .build(),
- IOReactorConfig.custom()
- .setIoThreadCount(2)
- .setTcpNoDelay(true)
- .setSoTimeout(Timeout.ofSeconds(10))
- .build(),
- tlsStrategyBuilder.build());
+ // Socket timeout must be longer than the longest feasible response timeout
+ Timeout socketTimeout = Timeout.ofMinutes(15);
+
+ // Note: MinimalH2AsyncClient does not support proxying or automatic retries
+ MinimalH2AsyncClient client = HttpAsyncClients.createHttp2Minimal(
+ H2Config.custom()
+ .setMaxConcurrentStreams(builder.maxStreamsPerConnection)
+ .setCompressionEnabled(true)
+ .setPushEnabled(false)
+ .setInitialWindowSize(Integer.MAX_VALUE)
+ .build(),
+ IOReactorConfig.custom()
+ .setIoThreadCount(2)
+ .setTcpNoDelay(true)
+ .setSoTimeout(socketTimeout)
+ .build(),
+ tlsStrategyBuilder.build());
+ ConnectionConfig connCfg = ConnectionConfig.custom()
+ .setSocketTimeout(socketTimeout)
+ .setConnectTimeout(Timeout.ofSeconds(10))
+ .build();
+ client.setConnectionConfigResolver(__ -> connCfg);
+ return client;
}
private static int portOf(URI url) {
@@ -193,15 +205,6 @@ class ApacheCluster implements Cluster {
: url.getPort();
}
- @SuppressWarnings("deprecation")
- private static RequestConfig createRequestConfig(FeedClientBuilderImpl b) {
- RequestConfig.Builder builder = RequestConfig.custom()
- .setConnectTimeout(Timeout.ofSeconds(10))
- .setConnectionRequestTimeout(Timeout.DISABLED);
- if (b.proxy != null) builder.setProxy(new HttpHost(b.proxy.getScheme(), b.proxy.getHost(), b.proxy.getPort()));
- return builder.build();
- }
-
private static class ApacheHttpResponse implements HttpResponse {
private final SimpleHttpResponse wrapped;