복붙노트

[SPRING] Spring 5 webflux Webclient에서 시간 초과를 설정하는 방법

SPRING

Spring 5 webflux Webclient에서 시간 초과를 설정하는 방법

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

하지만 내 웹 클라이언트에서 httpClient를 설정하는 방법을 알아낼 수 없습니다.

해결법

  1. ==============================

    1.WebFlux WebClient는 Apache Commons HTTP 클라이언트를 사용하지 않습니다. 사용자 지정 ClientHttpConnector를 통해 하나의 솔루션을 구현할 수도 있습니다. 기존 ReactorClientHttpConnector는 Netty를 기반으로합니다. 따라서 Netty 옵션을 사용하여 클라이언트를 구성하는 것을 고려해보십시오 (예 :

    WebFlux WebClient는 Apache Commons HTTP 클라이언트를 사용하지 않습니다. 사용자 지정 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()))
    

    최신 정보

    또한 ReadTimeoutHandler를 사용할 수 있습니다.

    .onChannelInit(channel -> 
            channel.pipeline()
               .addLast(new ReadTimeoutHandler(this.applicationConfig.getHttpClientConnectTimeout())))
    
  2. ==============================

    2.읽기 및 연결 시간 제한을 설정하려면 SO_TIMEOUT 옵션을 NIO를 사용하는 채널에 사용할 수 없기 때문에 (그리고 채널 '[id : 0xa716fcb2]'에 알 수없는 채널 옵션 'SO_TIMEOUT'경고를 제공하기 때문에) 아래의 방법을 사용합니다.

    읽기 및 연결 시간 제한을 설정하려면 SO_TIMEOUT 옵션을 NIO를 사용하는 채널에 사용할 수 없기 때문에 (그리고 채널 '[id : 0xa716fcb2]'에 알 수없는 채널 옵션 'SO_TIMEOUT'경고를 제공하기 때문에) 아래의 방법을 사용합니다.

    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. ==============================

    3.ReactorClientHttpConnector API가 Spring WebFlux 5.1 버전에서 변경되었습니다.

    ReactorClientHttpConnector API가 Spring WebFlux 5.1 버전에서 변경되었습니다.

    그래서 나는 다음을 수행합니다 (@joshiste 예제를 기반으로하는 Kotlin 구문).

    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()
    
  4. ==============================

    4.내가 어떻게했는지 (@Artem 덕분에)

    내가 어떻게했는지 (@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();
    
  5. from https://stackoverflow.com/questions/46235512/spring-5-webflux-how-to-set-a-timeout-on-webclient by cc-by-sa and MIT license