Reputation: 7809
I am using spring-webflux-5.2.8.RELEASE
and this is working "fine":
httpStatus = webClient
.post()
.uri(someUri)
.headers(someHeaders)
.bodyValue(someBody)
.exchange()
.map(ClientResponse::statusCode)
.timeout(someTimeout)
.doOnError(doSomething())
.onErrorResume(ex -> Mono.empty())
.block();
When an error is returned, there is no issue, as the connection is destroyed and is not put back in the connection pool:
DEBUG r.n.resources.PooledConnectionProvider - [id: 0xa23f78ad, L:/127.0.0.1:7524 ! R:localhost/127.0.0.1:8443] Channel closed, now 0 active connections and 0 inactive connections
But when i get a successful response, the next post will fail/timeout:
java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 10000ms in 'map' (and no fallback has been configured)
As i needed to troubleshoot, I used a fix connection pool of only 1 connection like so:
@Bean
public WebClient.Builder webClientBuilder(){
HttpClient httpClient = HttpClient.create(ConnectionProvider.create("pool", 1));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient));
}
I am guessing(i may be wrong as i am totally new to webclient and the reactive world) that the problem is that it is not releasing the connection after successfully getting the response and i think it is due to this.
When using a ClientResponse through the WebClient exchange() method, you have to make sure that the body is consumed or released...
I tried to do a releaseBody() like so(but that does not work as the next post is still failing):
.map(clientResponse -> {
HttpStatus statusCode = clientResponse.statusCode();
clientResponse.releaseBody();
return statusCode;
})
P.S I need to use the block(). That can't be changed as i need the response to move on, and i just need to get the status code. I am using WebClient, because i read somewhere that rest template is going to be deprecated in favor of ... WebClient. I hope someone can help.
I enabled metrics and indeed the connection is not released:
reactor_netty_connection_provider_fixedPool_total_connections{id="1591603494",remote_address="localhost:8443",} 1.0 reactor_netty_connection_provider_fixedPool_active_connections{id="1591603494",remote_address="localhost:8443",} 1.0
Found this: https://github.com/spring-projects/spring-framework/issues/20474
!
I tried with the default number of connections(i.e 500) and i can notice that the number of active connections keep increasing after each post i do :-(
[reactor-http-nio-2] DEBUG r.n.resources.PooledConnectionProvider - [id: 0x2316e048, L:/127.0.0.1:32787 - R:localhost/127.0.0.1:8443] Channel connected, now 7 active connections and 0 inactive connections
Upvotes: 3
Views: 7306
Reputation: 7809
This is what is working for me:
HttpStatus httpStatus = null;
Mono<HttpStatus> monoHttpStatus = null;
:
WebClient webClient = xxx.getWebClient();
:
try {
monoHttpStatus = webClient
.post()
.uri(someUri)
.headers(someHeaders)
.bodyValue(someBody)
.exchange()
.map(clientResponse ->
clientResponse.releaseBody().thenReturn(clientResponse.statusCode()))
.timeout(someTimeout)
.doOnError(Exception.class, e -> logger.error("An exception has occurred: ", e))
.onErrorResume(ex -> Mono.empty())
.block();
if(monoHttpStatus != null)
httpStatus = monoHttpStatus.block();
}
:
//SomeOtherClass
@Autowired
private WebClient.Builder webClientBuilder;
public WebClient getWebClient() {
:
webClient= webClientBuilder.baseUrl(baseUrl)
.build();
:
return webClient;
}
And i am now seeing this after the post is done:
DEBUG reactor.util.Loggers$Slf4JLogger.debug[249] [reactor-http-nio-1] [id: 0x6b0568a3, L:/127.0.0.1:10168 - R:localhost/127.0.0.1:8443] Releasing channel
DEBUG reactor.util.Loggers$Slf4JLogger.debug[254] [reactor-http-nio-1] [id: 0x6b0568a3, L:/127.0.0.1:10168 - R:localhost/127.0.0.1:8443] Channel cleaned, now 0 active connections and 1 inactive connections
Upvotes: 1