首页 文章

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

提问于
浏览
8

我正在尝试在我的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();

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

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();

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

4 回答

  • 10

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

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

    要么

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

    UPDATE

    我们也可以使用 ReadTimeoutHandler

    .onChannelInit(channel -> 
            channel.pipeline()
               .addLast(new ReadTimeoutHandler(this.applicationConfig.getHttpClientConnectTimeout())))
    
  • 0

    要设置读取和连接超时,我使用下面的方法,因为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();
    
  • 3

    这是我的表现(感谢@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();
    
  • 18

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

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

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

相关问题