Spring 5 webflux如何在Webclient上设置超时

Seb*_*Seb 15 spring reactor reactor-netty spring-webflux

我正在尝试在我的WebClient上设置超时,这是当前代码:

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();
Run Code Online (Sandbox Code Playgroud)

我需要添加超时和汇集策略,我正在考虑这样的事情:

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();
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚如何在我的webclient中设置httpClient

jos*_*ste 21

要设置读取和连接超时,我使用下面的方法,因为SO_TIMEOUT选项不适用于使用NIO的通道(并给出警告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();
Run Code Online (Sandbox Code Playgroud)

  • 伟大的!但是 ReactorClientHttpConnector 在 WebFlux 5.1 中发生了变化。 (2认同)

Art*_*lan 13

WebFlux WebClient不使用Apache Commons HTTP Client.虽然您可以通过自定义实现一个解决方案ClientHttpConnector.现有的ReactorClientHttpConnector是基于Netty.因此,请考虑使用Netty选项配置客户端,例如:

ReactorClientHttpConnector connector =
            new ReactorClientHttpConnector(options ->
                    options.option(ChannelOption.SO_TIMEOUT, this.applicationConfig.getHttpClientConnectTimeout()));
Run Code Online (Sandbox Code Playgroud)

要么

.onChannelInit(channel -> channel.config().setConnectTimeoutMillis(this.applicationConfig.getHttpClientConnectTimeout()))
Run Code Online (Sandbox Code Playgroud)

UPDATE

我们也可以使用ReadTimeoutHandler:

.onChannelInit(channel -> 
        channel.pipeline()
           .addLast(new ReadTimeoutHandler(this.applicationConfig.getHttpClientConnectTimeout())))
Run Code Online (Sandbox Code Playgroud)

  • `reactor.ipc.netty.options.ClientOptions.Builder中有`poolResources()```requestTimeout`确实等于`ChannelOption.SO_TIMEOUT`.`connectTimeoutMillis`绝对是关于连接的. (2认同)
  • 该API似乎已更改,这是现在的工作方式/sf/answers/3764671151/ (2认同)

mco*_*ive 11

Spring WebFlux 5.1版本中更改了ReactorClientHttpConnector API .

所以我做了以下(Kotlin语法,基于@joshiste示例):

val tcpClient = TcpClient.create()
    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000)
    .doOnConnected { connection ->
        connection.addHandlerLast(ReadTimeoutHandler(10))
            .addHandlerLast(WriteTimeoutHandler(10))
    }

val myWebClient = webClientBuilder
    .clientConnector(ReactorClientHttpConnector(HttpClient.from(tcpClient)))
    .baseUrl(myEndPoint)
    .build()
Run Code Online (Sandbox Code Playgroud)

  • 当使用您的解决方案时,我面临```来自 HttpClient 类型的 (TcpClient) 的方法已被弃用```。似乎“from(TcpClient)”也已被弃用。 (2认同)

pov*_*nko 5

随着Spring Webflux的更新,以下是一种适用于Java的解决方案(基于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();
Run Code Online (Sandbox Code Playgroud)

  • 很有帮助,但是`.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,SECONDS * 10)`我认为10应该是1000。 (3认同)