[英]Default read and connection timeouts for reactor-netty HttpClient
[英]how to configure pooled connection idle timeout in reactor-netty
我正在使用具有連接池的 reactor-netty http 客戶端(0.7.X 系列),並且想配置池連接的空閑超時,但不知道在哪里。
更准確地說,我需要以這樣一種方式配置 reactor-netty http 客戶端連接池,它會自動關閉在可配置超時內沒有看到任何活動的連接。 這些連接是打開的,但在某些(可配置的)時間內沒有字節傳入或傳出。
如何配置 reactor-netty http 客戶端以搶先關閉空閑連接?
我設法配置WebClient
(通過底層TcpClient
)以從reactor-netty 0.8.9 中的連接池中刪除超時時的空閑連接
我的解決方案部分基於關於IdleStateHandler的官方文檔,擴展了我對如何在創建HttpClient
實例時正確應用它的研究。
這是我如何做到的:
public class IdleCleanupHandler extends ChannelDuplexHandler {
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
final IdleState state = ((IdleStateEvent) evt).state();
if (state == IdleState.ALL_IDLE) { // or READER_IDLE / WRITER_IDLE
// close idling channel
ctx.close();
}
} else {
super.userEventTriggered(ctx, evt);
}
}
}
...
public static WebClient createWebClient(final String baseUrl, final int idleTimeoutSec) {
final TcpClient tcpClient = TcpClient.create(ConnectionProvider.fixed("fixed-pool"))
.bootstrap(bootstrap -> BootstrapHandlers.updateConfiguration(bootstrap, "idleTimeoutConfig",
(connectionObserver, channel) -> {
channel.pipeline()
.addLast("idleStateHandler", new IdleStateHandler(0, 0, idleTimeoutSec))
.addLast("idleCleanupHandler", new IdleCleanupHandler());
}));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
.baseUrl(baseUrl)
.build();
}
重要更新:
我的進一步測試表明,在bootstrap
掛鈎期間添加處理bootstrap
破壞池和套接字(通道)不會被Connection
重用。
添加處理程序的正確方法是:
public static WebClient createWebClient(final String baseUrl, final int idleTimeoutSec) {
final TcpClient tcpClient = TcpClient.create(ConnectionProvider.fixed("fixed-pool"))
.doOnConnected(conn -> {
final ChannelPipeline pipeline = conn.channel().pipeline();
if (pipeline.context("idleStateHandler") == null) {
pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, idleTimeoutSec))
.addLast("idleCleanupHandler", new IdleCleanupHandler());
}
});
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
.baseUrl(baseUrl)
.build();
}
注意:在reactor-netty
netty 0.9.x 中,將有一個標准的方法來為連接池中的連接配置空閑超時,請參閱此提交: https : //github.com/reactor/reactor-netty/pull/792
通過向通道管道添加 netty 寫入和讀取超時處理程序,我能夠在 0.7.x 分支上完成此操作。 但是,在 0.8.x 上,這種方法不再有效。
HttpClient httpClient = HttpClient
.create((HttpClientOptions.Builder builder) -> builder
.host(endpointUrl.getHost())
.port(endpointUrl.getPort())
.poolResources(PoolResources.fixed(connectionPoolName, maxConnections, timeoutPool))
.afterChannelInit(channel -> {
channel.pipeline()
// The write and read timeouts are serving as generic socket idle state handlers.
.addFirst("write_timeout", new WriteTimeoutHandler(timeoutIdle, TimeUnit.MILLISECONDS))
.addFirst("read_timeout", new ReadTimeoutHandler(timeoutIdle, TimeUnit.MILLISECONDS));
})
.build());
在具有 TCP 客戶端的 reactor-netty 0.9.x 中執行此操作的最簡單方法是使用以下方法,這是我從 @Vladimir-L 引用的鏈接中獲得的。 為您的問題配置“maxIdleTime”。
TcpClient timeoutClient = TcpClient.create(ConnectionProvider.fixed(onnectionPoolName, maxConnections, acquireTimeout,maxIdleTime));
由於 spring-boot-starter-webflux 我目前在 reactor-netty 0.8.2 並面臨同樣的問題,連接池在連接完成后保持連接打開 60 秒。
使用這種方法你不能配置超時,但你可以禁用它:
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.from(TcpClient.create()).keepAlive(false)))
.build()
.get()
.uri("someurl")
.retrieve()
.bodyToMono(String.class)
對於 Reactor Netty 版本 1,您需要創建一個reactor.netty.resources.ConnectionProvider
,它將包含空閑時間配置,然后在創建reactor.netty.http.client.HttpClient
時使用它。
我正在使用 Spring,所以我然后使用它來創建一個 Spring org.springframework.http.client.reactive.ClientHttpConnector
,如下所示。
ConnectionProvider connectionProvider = ConnectionProvider.builder("Name")
.maxIdleTime(Duration.ofSeconds(10))
.build();
HttpClient httpClient = HttpClient.create(connectionProvider)
.compress(true);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl(host);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.