Spring 5 webflux How to set timeout on Webclient

I am trying to set a timeout on my WebClient, here is the current code:

SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build(); ClientHttpConnector httpConnector = new ReactorClientHttpConnector(opt -> { opt.sslContext(sslContext); HttpClientOptions option = HttpClientOptions.builder().build(); opt.from(option); }); return WebClient.builder().clientConnector(httpConnector).defaultHeader("Authorization", xxxx) .baseUrl(this.opusConfig.getBaseURL()).build(); 

I need to add a timeout, as well as a merge strategy, I was thinking about something like this:

 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(this.applicationConfig.getHttpClientMaxPoolSize()); cm.setDefaultMaxPerRoute(this.applicationConfig.getHttpClientMaxPoolSize()); cm.closeIdleConnections(this.applicationConfig.getServerIdleTimeout(), TimeUnit.MILLISECONDS); RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(this.applicationConfig.getHttpClientSocketTimeout()) .setConnectTimeout(this.applicationConfig.getHttpClientConnectTimeout()) .setConnectionRequestTimeout(this.applicationConfig.getHttpClientRequestTimeout()).build(); CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(cm).build(); 

But I can not figure out how to install httpClient in my web client

+10
source share
6 answers

WebFlux WebClient does not use the Apache Commons HTTP client. Although you can implement one solution through a custom ClientHttpConnector . The existing ReactorClientHttpConnector based on Netty. Therefore, consider using Netty options to configure the client, for example:

 ReactorClientHttpConnector connector = new ReactorClientHttpConnector(options -> options.option(ChannelOption.SO_TIMEOUT, this.applicationConfig.getHttpClientConnectTimeout())); 

or

 .onChannelInit(channel -> channel.config().setConnectTimeoutMillis(this.applicationConfig.getHttpClientConnectTimeout())) 

UPDATE

We can also use ReadTimeoutHandler :

 .onChannelInit(channel -> channel.pipeline() .addLast(new ReadTimeoutHandler(this.applicationConfig.getHttpClientConnectTimeout()))) 
+10
source

To set the read and connection timeout, I use the method below because the SO_TIMEOUT option is not available for channels using NIO (and giving the warning Unknown channel option 'SO_TIMEOUT' for channel '[id: 0xa716fcb2]' )

 ReactorClientHttpConnector connector = new ReactorClientHttpConnector( options -> options.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000) .compression(true) .afterNettyContextInit(ctx -> { ctx.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS)); })); return WebClient.builder() .clientConnector(connector) .build(); 
+20
source

ReactorClientHttpConnector API changed in Spring WebFlux 5.1 .

So I do the following (Kotlin syntax based on @joshiste example):

 val tcpClient = TcpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) .doOnConnected { connection -> connection.addHandlerLast(ReadTimeoutHandler(10)) .addHandlerLast(WriteTimeoutHandler(10)) } val myWebClient = WebClient.builder() .clientConnector(ReactorClientHttpConnector(HttpClient.from(tcpClient))) .baseUrl(myEndPoint) .build() 
+11
source

Here's how I did it (thanks @Artem)

 SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build(); ClientHttpConnector httpConnector = new ReactorClientHttpConnector(options -> { options.sslContext(sslContext); options.option(ChannelOption.SO_TIMEOUT, this.applicationConfig.getHttpClientRequestTimeout()); options.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.applicationConfig.getHttpClientConnectTimeout()); options.poolResources(PoolResources.fixed("myPool", this.applicationConfig.getHttpClientMaxPoolSize())); }); return WebClient.builder().clientConnector(httpConnector).defaultHeader("Authorization", "xxxx") .baseUrl(this.config.getBaseURL()).build(); 
+3
source

Since Spring Webflux has been updated, here is a solution that works for Java (based on the answer above for Kotlin):

 TcpClient timeoutClient = TcpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, SECONDS*1000) .doOnConnected( c -> c.addHandlerLast(new ReadTimeoutHandler(SECONDS)) .addHandlerLast(new WriteTimeoutHandler(SECONDS))); return webClientBuilder.baseUrl(YOUR_URL) .clientConnector(new ReactorClientHttpConnector(HttpClient.from(timeoutClient))) .build(); 
+2
source

Based on the comment above, if you want to add a socket timeout, just add it as another parameter in the same timeoutClient.

 TcpClient timeoutClient = TcpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, SECONDS*10) //Connect Timeout .option(ChannelOption.SO_TIMEOUT,1000) // Socket Timeout .doOnConnected( c -> c.addHandlerLast(new ReadTimeoutHandler(SECONDS)) .addHandlerLast(new WriteTimeoutHandler(SECONDS))); return webClientBuilder.baseUrl(YOUR_URL) .clientConnector(new ReactorClientHttpConnector(HttpClient.from(timeoutClient))) .build(); 
0
source

Source: https://habr.com/ru/post/1271831/


All Articles