超时设置
由于 Netty 是 Spring WebFlux 的默认客户端库,本文将以为 Reactor Netty HttpClient 为例
响应超时
响应超时是指发送请求后等待接收响应的时间。可以使用 responseTimeout()
方法为客户端配置它:
// 配置超时时间为 1s,Netty 默认不设置响应超时。
HttpClient httpClient = HttpClient.create().responseTimeout(Duration.ofSeconds(1));
WebClient webClient = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();
连接超时
连接超时是客户端和服务器之间建立链接的必须时间段,可以使用不同的 Channel Option key
和 option()
方法来设置。Netty 默认值为 30 秒。
HttpClient httpClient = HttpClient.create().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000);
WebClient webClient = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();
此外,还可以配置 keep-alive
选项,它可以在连接空闲时发送 TCP 保活探测报文。
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.SO_KEEPALIVE, true)
.option(EpollChannelOption.TCP_KEEPIDLE, 300)
.option(EpollChannelOption.TCP_KEEPINTVL, 60)
.option(EpollChannelOption.TCP_KEEPCNT, 8);
启用了 keep-alive
,在空闲 5 分钟后以 60 秒为间隔进行探测。还将连接中断前的最大探测次数设置为 8 次。
当连接在给定时间内未建立或被放弃时,会抛出 ConnectTimeoutException
异常。
读写超时
读取超时发生在一定时间内没有读取数据,而写入超时发生在写入操作无法在特定时间内完成。 HttpClient
允许配置额外的 Handler
来配置这些超时:
HttpClient client = HttpClient.create()
.doOnConnected(conn -> conn
.addHandler(new ReadTimeoutHandler(10, TimeUnit.SECONDS))
.addHandler(new WriteTimeoutHandler(10)));
通过 doOnConnected()
方法配置连接回调,并在其中添加了 ReadTimeOutHandler
和 WriteTimeOutHandler
实例处理读写超时,超时时间都设置为 10 秒。
这些 Handler
的构造函数接受两种不同的参数。可以指定 TimeUnit
以及对应的值,或者只指定一个值,默认的单位是秒。
底层的 Netty 库提供了 ReadTimeoutException
和 WriteTimeoutException
异常类来表示对应的超时异常。
SSL/TLS 超时
握手超时是系统在停止操作之前尝试建立 SSL 连接的时间,可以通过 secure()
方法设置 SSL 配置
HttpClient client = HttpClient.create()
.secure(spec -> spec.sslContext(SslContextBuilder.forClient())
.defaultConfiguration(SslProvider.DefaultConfigurationType.TCP)
.handshakeTimeout(Duration.ofSeconds(30))
.closeNotifyFlushTimeout(Duration.ofSeconds(10))
.closeNotifyReadTimeout(Duration.ofSeconds(10)));
如上,将握手超时设置为 30 秒(默认值:10 秒),将 close_notify flush(默认值:3 秒)和 read(默认值:0 秒)超时设置为 10 秒。所有方法都由 SslProvider.Builder
接口提供。
当由于超时而导致握手失败时,将抛出 SslHandshakeTimeoutException
。
代理超时
HttpClient 还支持代理功能。如果与对等端的连接在指定时间内未完成,连接将失败。可以通过 proxy()
设置这个超时时间:
HttpClient httpClient= HttpClient.create()
.proxy(spec -> spec.type(ProxyProvider.Proxy.HTTP)
.host("proxy")
.port(8080)
.connectTimeoutMillis(30000));
使用 connectTimeoutMillis()
将超时时间设置为 30 秒,默认值为 10 秒。
在连接失败时,Netty 会抛出 ProxyConnectException
。
请求超时
在上一节中,使用 HttpClient 全局配置了不同的超时。不过,也可以独立于全局设置,设置特定请求响应的超时。
使用 HttpClientRequest 设置响应超时
WebClient webClient= webClient.get()
.uri("https://baeldung.com/path")
.httpRequest(httpRequest -> {
HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
reactorRequest.responseTimeout(Duration.ofSeconds(2));
});
如上,使用 WebClient
的 httpRequest()
方法来访问底层 Netty 库的原生 HttpClientRequest
。接着,将超时值设置为 2 秒。
该设置会覆盖 HttpClient 层面的任何响应超时设置。也可以将此值设置为 null,以删除任何先前配置的值。
配置 “响应式流” 超时
Reactor Netty 使用 Reactor Core 作为 Reactive Stream 实现。可以使用 Mono 和 Flux Publisher 提供的 timeout()
方法来配置另一个超时:
WebClient webClient = webClient.get()
.uri("https://baeldung.com/path")
.retrieve()
.bodyToFlux(JsonNode.class)
.timeout(Duration.ofSeconds(5));
在这种情况下,如果在 5 秒内没有项目到达,就会出现 TimeoutException 异常。
最好使用 Reactor Netty 中提供的更具体的超时配置选项,因为它们能为特定目的和用例提供更多控制。
timeout()
方法适用于整个操作,包括与远程建立连接到接收响应。它不会覆盖任何与 HttpClient 相关的设置。
最后更新于
这有帮助吗?