diff --git a/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpClientAgileConfiguration.java b/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpClientAgileConfiguration.java index 59f78fe40..bd1291347 100644 --- a/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpClientAgileConfiguration.java +++ b/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpClientAgileConfiguration.java @@ -60,6 +60,8 @@ public class HttpClientAgileConfiguration extends HttpClientModuleDefaultConfigu private boolean enableValueTracing; private MimeToContentTypeMapper consumesMimeTypeMapper; private MimeToContentTypeMapper producesMimeTypeMapper; + private int maxConnectionsPerRoute; + private int maxConnectionsTotal; public HttpClientAgileConfiguration() { refresh(); @@ -119,5 +121,7 @@ public void refresh() { sslKeyStoreType = configString(HTTP_COMMUNICATION_SECTION_ID, SSL_KEY_STORE_TYPE, super.getSslKeyStoreType()); sslKeyStoreFilePath = configString(HTTP_COMMUNICATION_SECTION_ID, SSL_KEY_STORE_FILE_PATH, super.getSslKeyStoreFilePath()); sslKeyStorePassword = configString(HTTP_COMMUNICATION_SECTION_ID, SSL_KEY_STORE_PASSWORD, super.getSslKeyStorePassword()); + maxConnectionsPerRoute = configInt(HTTP_COMMUNICATION_SECTION_ID, MAX_CONNECTIONS_PER_ROUTE, super.getMaxConnectionsPerRoute()); + maxConnectionsTotal = configInt(HTTP_COMMUNICATION_SECTION_ID, MAX_CONNECTIONS_TOTAL, super.getMaxConnectionsTotal()); } } \ No newline at end of file diff --git a/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpConfigKeys.java b/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpConfigKeys.java index 0a7a501eb..b91be7a96 100644 --- a/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpConfigKeys.java +++ b/application-config-extensions/src/main/java/ru/art/config/extensions/http/HttpConfigKeys.java @@ -33,8 +33,11 @@ public interface HttpConfigKeys { String SSL = "ssl"; String SSL_KEY_STORE_FILE_PATH = "sslKeyStoreFilePath"; String SSL_KEY_STORE_PASSWORD = "sslKeyStorePassword"; + String MAX_CONNECTIONS_PER_ROUTE = "maxConnectionsPerRoute"; + String MAX_CONNECTIONS_TOTAL = "maxConnectionsTotal"; String SSL_KEY_STORE_TYPE = "sslKeyStoreType"; String CONSUMES_MIME_TYPE = "consumesMimeType"; String PRODUCES_MIME_TYPE = "producesMimeType"; String WEB = "web"; + } diff --git a/application-grpc-client/src/main/java/ru/art/grpc/client/communicator/GrpcCommunicatorChannelFactory.java b/application-grpc-client/src/main/java/ru/art/grpc/client/communicator/GrpcCommunicatorChannelFactory.java index 538d1ba53..fbadca81c 100644 --- a/application-grpc-client/src/main/java/ru/art/grpc/client/communicator/GrpcCommunicatorChannelFactory.java +++ b/application-grpc-client/src/main/java/ru/art/grpc/client/communicator/GrpcCommunicatorChannelFactory.java @@ -1,6 +1,10 @@ package ru.art.grpc.client.communicator; import io.grpc.*; +import io.grpc.internal.*; +import io.grpc.util.*; +import io.netty.resolver.*; +import ru.art.grpc.client.interceptor.*; import static io.grpc.ManagedChannelBuilder.*; import static java.util.concurrent.TimeUnit.*; import static ru.art.core.context.Context.*; diff --git a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationConfiguration.java b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationConfiguration.java index b1552e6f4..659e809da 100644 --- a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationConfiguration.java +++ b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationConfiguration.java @@ -26,12 +26,16 @@ import ru.art.entity.Value; import ru.art.entity.interceptor.*; import ru.art.entity.mapper.*; +import ru.art.http.client.constants.*; +import ru.art.http.client.constants.HttpClientModuleConstants.*; import ru.art.http.client.handler.*; import ru.art.http.client.interceptor.*; import ru.art.http.constants.*; import static lombok.AccessLevel.*; import static ru.art.core.context.Context.*; import static ru.art.core.factory.CollectionsFactory.*; +import static ru.art.http.client.constants.HttpClientModuleConstants.HttpClientKeepAliveHeaderStrategy.CONSIDER; +import static ru.art.http.client.constants.HttpClientModuleConstants.HttpClientKeepAliveHeaderStrategy.IGNORE; import static ru.art.http.client.module.HttpClientModule.*; import static ru.art.http.constants.HttpMethodType.*; import java.nio.charset.*; @@ -54,6 +58,7 @@ class HttpCommunicationConfiguration { private HttpCommunicationCancellationHandler cancellationHandler; private boolean chunkedBody; private boolean gzipCompressedBody; + private HttpClientKeepAliveHeaderStrategy keepAliveResponseHeaderStrategy = IGNORE; private RequestConfig requestConfig = httpClientModule().getRequestConfig(); private HttpVersion httpProtocolVersion = httpClientModule().getHttpVersion(); private MimeToContentTypeMapper producesMimeType = httpClientModule().getProducesMimeTypeMapper(); diff --git a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationExecutor.java b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationExecutor.java index fa8c6795d..84f4b16b3 100644 --- a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationExecutor.java +++ b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicationExecutor.java @@ -32,6 +32,7 @@ import ru.art.entity.Value; import ru.art.entity.interceptor.*; import ru.art.entity.mapper.*; +import ru.art.http.client.constants.*; import ru.art.http.client.exception.*; import ru.art.http.client.handler.*; import ru.art.http.client.interceptor.*; @@ -51,6 +52,8 @@ import static ru.art.http.client.body.descriptor.HttpBodyDescriptor.*; import static ru.art.http.client.builder.HttpUriBuilder.*; import static ru.art.http.client.constants.HttpClientExceptionMessages.*; +import static ru.art.http.client.constants.HttpClientModuleConstants.HttpClientKeepAliveHeaderStrategy.CONSIDER; +import static ru.art.http.client.constants.HttpClientModuleConstants.HttpClientKeepAliveHeaderStrategy.IGNORE; import static ru.art.http.client.module.HttpClientModule.*; import static ru.art.logging.LoggingModule.*; import javax.annotation.*; @@ -88,7 +91,7 @@ private static ResponseType executeHttpUriRequest(HttpCommunicati } catch (Throwable throwable) { throw new HttpClientException(throwable); } finally { - if (nonNull(httpResponse)) { + if (nonNull(httpResponse) && configuration.getKeepAliveResponseHeaderStrategy() == IGNORE) { try { httpResponse.close(); } catch (Throwable closableThrowable) { diff --git a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicator.java b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicator.java index 4d5e7fa83..252442837 100644 --- a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicator.java +++ b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicator.java @@ -76,6 +76,10 @@ static HttpCommunicator httpCommunicator(HttpCommunicationTargetConfiguration ta HttpCommunicator options(); + HttpCommunicator considerKeepAliveResponseHeader(); + + HttpCommunicator ignoreKeepAliveResponseHeader(); + HttpCommunicator delete(); HttpCommunicator trace(); diff --git a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicatorImplementation.java b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicatorImplementation.java index b800b9fff..87d3a119c 100644 --- a/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicatorImplementation.java +++ b/application-http-client/src/main/java/ru/art/http/client/communicator/HttpCommunicatorImplementation.java @@ -19,41 +19,37 @@ package ru.art.http.client.communicator; import lombok.*; -import org.apache.http.HttpVersion; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.*; +import org.apache.http.client.config.*; +import org.apache.http.impl.client.*; +import org.apache.http.impl.nio.client.*; import org.apache.logging.log4j.*; -import ru.art.core.validator.BuilderValidator; +import ru.art.core.validator.*; import ru.art.entity.Value; -import ru.art.entity.interceptor.ValueInterceptor; -import ru.art.entity.mapper.ValueFromModelMapper; -import ru.art.entity.mapper.ValueToModelMapper; -import ru.art.http.client.communicator.HttpCommunicator.HttpAsynchronousCommunicator; -import ru.art.http.client.handler.HttpCommunicationCancellationHandler; -import ru.art.http.client.handler.HttpCommunicationExceptionHandler; -import ru.art.http.client.handler.HttpCommunicationResponseHandler; -import ru.art.http.client.interceptor.HttpClientInterceptor; -import ru.art.http.client.model.HttpCommunicationTargetConfiguration; -import ru.art.http.constants.MimeToContentTypeMapper; -import static java.util.Optional.ofNullable; -import static lombok.AccessLevel.PRIVATE; -import static ru.art.core.caster.Caster.cast; -import static ru.art.core.checker.CheckerForEmptiness.isNotEmpty; -import static ru.art.core.constants.StringConstants.COLON; -import static ru.art.core.constants.StringConstants.SCHEME_DELIMITER; -import static ru.art.core.context.Context.contextConfiguration; -import static ru.art.core.extension.NullCheckingExtensions.getOrElse; -import static ru.art.core.extension.StringExtensions.emptyIfNull; -import static ru.art.core.wrapper.ExceptionWrapper.ignoreException; -import static ru.art.http.client.communicator.HttpCommunicationExecutor.executeAsynchronousHttpRequest; -import static ru.art.http.client.communicator.HttpCommunicationExecutor.executeSynchronousHttpRequest; -import static ru.art.http.client.module.HttpClientModule.httpClientModule; +import ru.art.entity.interceptor.*; +import ru.art.entity.mapper.*; +import ru.art.http.client.communicator.HttpCommunicator.*; +import ru.art.http.client.handler.*; +import ru.art.http.client.interceptor.*; +import ru.art.http.client.model.*; +import ru.art.http.constants.*; +import static java.util.Optional.*; +import static lombok.AccessLevel.*; +import static ru.art.core.caster.Caster.*; +import static ru.art.core.checker.CheckerForEmptiness.*; +import static ru.art.core.constants.StringConstants.*; +import static ru.art.core.context.Context.*; +import static ru.art.core.extension.NullCheckingExtensions.*; +import static ru.art.core.extension.StringExtensions.*; +import static ru.art.core.wrapper.ExceptionWrapper.*; +import static ru.art.http.client.communicator.HttpCommunicationExecutor.*; +import static ru.art.http.client.constants.HttpClientModuleConstants.HttpClientKeepAliveHeaderStrategy.*; +import static ru.art.http.client.module.HttpClientModule.*; import static ru.art.http.constants.HttpMethodType.*; -import static ru.art.logging.LoggingModule.loggingModule; -import java.nio.charset.Charset; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; +import static ru.art.logging.LoggingModule.*; +import java.nio.charset.*; +import java.util.*; +import java.util.concurrent.*; public class HttpCommunicatorImplementation implements HttpCommunicator, HttpAsynchronousCommunicator { private final BuilderValidator validator = new BuilderValidator(HttpCommunicator.class.getName()); @@ -224,6 +220,18 @@ public HttpCommunicator gzipCompressed() { return this; } + @Override + public HttpCommunicator ignoreKeepAliveResponseHeader() { + configuration.setKeepAliveResponseHeaderStrategy(IGNORE); + return this; + } + + @Override + public HttpCommunicator considerKeepAliveResponseHeader() { + configuration.setKeepAliveResponseHeaderStrategy(CONSIDER); + return this; + } + @Override public HttpCommunicator requestEncoding(String encoding) { configuration.setRequestContentEncoding(emptyIfNull(encoding)); diff --git a/application-http-client/src/main/java/ru/art/http/client/configuration/HttpClientModuleConfiguration.java b/application-http-client/src/main/java/ru/art/http/client/configuration/HttpClientModuleConfiguration.java index c4b03fbec..fd67aae52 100644 --- a/application-http-client/src/main/java/ru/art/http/client/configuration/HttpClientModuleConfiguration.java +++ b/application-http-client/src/main/java/ru/art/http/client/configuration/HttpClientModuleConfiguration.java @@ -20,12 +20,14 @@ import lombok.*; import org.apache.http.*; +import org.apache.http.client.*; import org.apache.http.client.config.*; import org.apache.http.config.*; import org.apache.http.impl.client.*; import org.apache.http.impl.nio.client.*; import org.apache.http.impl.nio.reactor.*; import org.zalando.logbook.httpclient.*; +import ru.art.http.client.constants.*; import ru.art.http.client.exception.*; import ru.art.http.client.interceptor.*; import ru.art.http.client.model.*; @@ -52,6 +54,10 @@ import java.util.*; public interface HttpClientModuleConfiguration extends HttpModuleConfiguration { + int getMaxConnectionsPerRoute(); + + int getMaxConnectionsTotal(); + CloseableHttpClient getClient(); CloseableHttpAsyncClient getAsynchronousClient(); @@ -97,6 +103,8 @@ default HttpCommunicationTargetConfiguration getCommunicationTargetConfiguration @Getter class HttpClientModuleDefaultConfiguration extends HttpModuleDefaultConfiguration implements HttpClientModuleConfiguration { + int maxConnectionsPerRoute = DEFAULT_MAX_CONNECTIONS_PER_ROUTE; + int maxConnectionsTotal = DEFAULT_MAX_CONNECTIONS_TOTAL; private final RequestConfig requestConfig = RequestConfig.DEFAULT; private final SocketConfig socketConfig = SocketConfig.DEFAULT; private final ConnectionConfig connectionConfig = ConnectionConfig.DEFAULT; @@ -124,6 +132,8 @@ class HttpClientModuleDefaultConfiguration extends HttpModuleDefaultConfiguratio @SuppressWarnings({"Duplicates", "WeakerAccess"}) protected CloseableHttpAsyncClient createAsyncHttpClient() { HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom() + .setMaxConnPerRoute(getMaxConnectionsPerRoute()) + .setMaxConnTotal(getMaxConnectionsTotal()) .setDefaultRequestConfig(getRequestConfig()) .setDefaultIOReactorConfig(getIoReactorConfig()) .setDefaultConnectionConfig(getConnectionConfig()); @@ -149,6 +159,8 @@ protected CloseableHttpAsyncClient createAsyncHttpClient() { @SuppressWarnings({"Duplicates", "WeakerAccess"}) protected CloseableHttpClient createHttpClient() { HttpClientBuilder clientBuilder = HttpClients.custom() + .setMaxConnPerRoute(getMaxConnectionsPerRoute()) + .setMaxConnTotal(getMaxConnectionsTotal()) .setDefaultRequestConfig(getRequestConfig()) .setDefaultConnectionConfig(getConnectionConfig()) .setDefaultSocketConfig(getSocketConfig()) diff --git a/application-http-client/src/main/java/ru/art/http/client/constants/HttpClientModuleConstants.java b/application-http-client/src/main/java/ru/art/http/client/constants/HttpClientModuleConstants.java index a4c537105..75614837b 100644 --- a/application-http-client/src/main/java/ru/art/http/client/constants/HttpClientModuleConstants.java +++ b/application-http-client/src/main/java/ru/art/http/client/constants/HttpClientModuleConstants.java @@ -25,4 +25,11 @@ public interface HttpClientModuleConstants { String TRACE_ID_HEADER = "X-Trace-Id"; int DEFAULT_HTTP_CLIENT_TIMEOUT = 10000; int RESPONSE_BUFFER_DEFAULT_SIZE = 4096; + int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; + int DEFAULT_MAX_CONNECTIONS_TOTAL = 20; + + enum HttpClientKeepAliveHeaderStrategy { + IGNORE, + CONSIDER + } } diff --git a/application-http-client/src/main/java/ru/art/http/client/factory/HttpClientsFactory.java b/application-http-client/src/main/java/ru/art/http/client/factory/HttpClientsFactory.java index a2115db1d..469a563a9 100644 --- a/application-http-client/src/main/java/ru/art/http/client/factory/HttpClientsFactory.java +++ b/application-http-client/src/main/java/ru/art/http/client/factory/HttpClientsFactory.java @@ -40,6 +40,8 @@ public class HttpClientsFactory { @SuppressWarnings("Duplicates") public static CloseableHttpAsyncClient createAsyncHttpClient(HttpClientConfiguration configuration) { HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom() + .setMaxConnPerRoute(configuration.getMaxConnectionsPerRoute()) + .setMaxConnTotal(configuration.getMaxConnectionsTotal()) .setDefaultRequestConfig(configuration.getRequestConfig()) .setDefaultIOReactorConfig(configuration.getIoReactorConfig()) .setDefaultConnectionConfig(configuration.getConnectionConfig()); @@ -67,6 +69,8 @@ public static CloseableHttpAsyncClient createAsyncHttpClient(HttpClientConfigura @SuppressWarnings("Duplicates") public static CloseableHttpClient createHttpClient(HttpClientConfiguration configuration) { HttpClientBuilder clientBuilder = HttpClients.custom() + .setMaxConnPerRoute(configuration.getMaxConnectionsPerRoute()) + .setMaxConnTotal(configuration.getMaxConnectionsTotal()) .setDefaultRequestConfig(configuration.getRequestConfig()) .setDefaultConnectionConfig(configuration.getConnectionConfig()) .setDefaultSocketConfig(configuration.getSocketConfig()) diff --git a/application-http-client/src/main/java/ru/art/http/client/model/HttpClientConfiguration.java b/application-http-client/src/main/java/ru/art/http/client/model/HttpClientConfiguration.java index bce103ad5..95b5d48e0 100644 --- a/application-http-client/src/main/java/ru/art/http/client/model/HttpClientConfiguration.java +++ b/application-http-client/src/main/java/ru/art/http/client/model/HttpClientConfiguration.java @@ -47,4 +47,8 @@ public class HttpClientConfiguration { private final String sslKeyStorePassword = httpClientModule().getSslKeyStorePassword(); @Builder.Default private final boolean enableRawDataTracing = httpClientModule().isEnableRawDataTracing(); + @Builder.Default + private final int maxConnectionsPerRoute = httpClientModule().getMaxConnectionsPerRoute(); + @Builder.Default + private final int maxConnectionsTotal = httpClientModule().getMaxConnectionsTotal(); } \ No newline at end of file