在Spring WebFlux webclient中设置超时

问题描述:

我正在使用Spring Webflux WebClient从我的Spring启动应用程序进行REST调用。并且每次都在30秒内获得超时。

I'm using Spring Webflux WebClient to make a REST call from my Spring boot application. And every time getting a timeout in 30 seconds.

以下是我尝试在Spring webfulx的WebClient中设置套接字超时的一些代码。

Here is some code I tried to set socket timeout in WebClient of Spring webfulx.

 - ReactorClientHttpConnector connector = new ReactorClientHttpConnector(options -> options
           .option(ChannelOption.SO_TIMEOUT, 600000).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 600000));
 - ReactorClientHttpConnector connector = new ReactorClientHttpConnector(
           options -> options.afterChannelInit(chan -> {
                chan.pipeline().addLast(new ReadTimeoutHandler(600000));
            }));
 - ReactorClientHttpConnector connector1 = new ReactorClientHttpConnector(options -> options
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 600000).afterNettyContextInit(ctx -> {
                ctx.addHandlerLast(new ReadTimeoutHandler(600000, TimeUnit.MILLISECONDS));
            }));

并尝试使用clientConnector方法在WebClient中添加上面的连接器设置。

And tried to add this above connector setting in "WebClient" by using "clientConnector" method.

并且还尝试将超时设置如下:

And also tried to set timeout as below:

webClient.get().uri(builder -> builder.path("/result/{name}/sets")
                    .queryParam("q", "kind:RECORDS")
                    .queryParam("offset", offset)
                    .queryParam("limit", RECORD_COUNT_LIMIT)
                    .build(name))
            .header(HttpHeaders.AUTHORIZATION, accessToken)
            .exchange().<b><i>timeout(Duration.ofMillis(600000))</i></b>
            .flatMap(response -> handleResponse(response, name, offset));

以上所有选项均不适合我。

None of the above options is working for me.

我正在使用org.springframework.boot:spring-boot-gradle-plugin:2.0.0.M7,它们具有org.springframework的依赖性:spring-webflux:5.0.2.RELEASE。

I'm using org.springframework.boot:spring-boot-gradle-plugin:2.0.0.M7 which interally have dependecy of org.springframework:spring-webflux:5.0.2.RELEASE.

请在这里建议,如果我在这里做错了,请告诉我。

Please suggest here and let me know if I'm doing anything wrong here.

I've tried reproducing the issue and couldn't. Using reactor-netty 0.7.5.RELEASE.

我不确定你说的是什么超时。

I'm not sure about which timeout you're talking about.

可以使用 ChannelOption.CONNECT_TIMEOUT_MILLIS 配置连接超时。我在连接日志消息和实际错误之间得到10秒:

Connection timeout can be configured with ChannelOption.CONNECT_TIMEOUT_MILLIS. I'm getting 10 seconds between the "connecting" log message and the actual error:

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(options -> options
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)))
    .build();

webClient.get().uri("http://10.0.0.1/resource").exchange()
    .doOnSubscribe(subscription -> logger.info("connecting"))
    .then()
    .doOnError(err -> logger.severe(err.getMessage()))
    .block();

如果您正在谈论读/写超时,那么您可以查看Netty的 ReadTimeoutHandler WriteTimeoutHandler

If you're talking about read/write timeouts, then you can look at Netty's ReadTimeoutHandler and WriteTimeoutHandler.

一个完整的示例可能如下所示:

A full example could look like this:

ReactorClientHttpConnector connector = new ReactorClientHttpConnector(options ->
        options.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
                .onChannelInit(channel -> {
                        channel.pipeline().addLast(new ReadTimeoutHandler(10))
                                .addLast(new WriteTimeoutHandler(10));
                return true;
        }).build());

从Reactor Netty 0.8和Spring Framework 5.1开始,配置现在看起来像这样:

As of Reactor Netty 0.8 and Spring Framework 5.1, the configuration now looks like this:

TcpClient tcpClient = TcpClient.create()
                 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
                 .doOnConnected(connection ->
                         connection.addHandlerLast(new ReadTimeoutHandler(10))
                                   .addHandlerLast(new WriteTimeoutHandler(10)));
WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
    .build();

可能将以下内容添加到 application.properties 将提供有关HTTP级别发生的更多信息:

Maybe adding the following to your application.properties will provide more information on what's happening at the HTTP level:

logging.level.reactor.ipc.netty.channel.ContextHandler=debug
logging.level.reactor.ipc.netty.http.client.HttpClient=debug