diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2023-05-05 10:44:19 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2023-05-05 10:44:20 +0200 |
commit | 005299acdb85b626b8c2fea2677c7f862d7b2fa6 (patch) | |
tree | 809ad4acf8398b4fa941ef0a1fb5004c191e0bb3 /vespa-feed-client/src/main/java | |
parent | 1d0076c194c06b2306599ac5b68db702a17d9f73 (diff) |
Ensure socket timeout is longer than response timeouts
Resolve all deprecation warnings
Diffstat (limited to 'vespa-feed-client/src/main/java')
-rw-r--r-- | vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java | 57 |
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; |