Я использую Spring WebClient в своем приложении Spring Boot для вызова внешних API. Приложение работает на JBoss EAP 7.3.x, используется Java 8, Springboot 2.7.1. Я настроил пул соединений для повышения производительности, но столкнулся с постоянной проблемой:
У меня есть подробные журналы, которые показывают, что соединение закрывается после бездействия:
DEBUG reactor.netty.http.client.HttpClient - [....] READ COMPLETE
DEBUG reactor.netty.http.client.HttpClient - [....] USER_EVENT: SslCloseCompletionEvent
DEBUG reactor.netty.http.client.HttpClient - [....] INACTIVE
DEBUG r.n.r.DefaultPooledConnectionProvider - [1a115ad9, L:/ip_address ! test.mysite.net/ip_of_target:443] onStateChange(PooledConnection{channel=[id: 1a115ad9, L:/ip_address ! R
.mysite.net/target_ip:443}}, [disconnecting])
DEBUG reactor.netty.http.client.HttpClient - [....] UNREGISTERED
@Configuration
public class WebClientConfig {
@Bean
public ConnectionProvider connectionProvider() {
return ConnectionProvider.builder("MyApplicationConnection")
.maxConnections(100)
.pendingAcquireTimeout(Duration.ofSeconds(60))
.maxIdleTime(Duration.ofMinutes(30))
.maxLifeTime(Duration.ofMinutes(60))
.evictInBackground(Duration.ofMinutes(5))
.build();
}
@Bean
public HttpClient httpClient(ConnectionProvider connectionProvider) {
return HttpClient.create(connectionProvider)
.doOnConnected(connection ->
connection.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10)))
.wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);
}
@Bean
public WebClient webClient(HttpClient httpClient) {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl("https://test.mysite.net")
.defaultHeader(HttpHeaders.CONNECTION, "keep-alive")
.build();
}
}
Я пробовал увеличить maxIdleTime и maxLifeTime, но это не дало никакого эффекта. Я хочу, чтобы мои последующие запросы выполнялись быстрее, даже если есть период бездействия. По сути, мое приложение представляет собой приложение на основе API, которое будет вызывать другие API с помощью веб-клиента. Если в течение некоторого времени к моему API не поступают запросы, это не должно замедлить следующий запрос.
Проблема была решена после включения кэширования DNS. Да, неактивные соединения освобождаются, но проблема была связана с дополнительными поисками DNS при каждом новом соединении.
return HttpClient.create(connectionProvider)
.resolver(DefaultAddressResolverGroup.INSTANCE)