根据错误状态代码关闭反应堆网络连接

2022-04-04 00:00:00 java netty reactor-netty

为了将数据发送到远程内容交付网络,我通过Spring Webflow框架使用了Reator Netty。当客户端请求完成时,默认的反应程序Netty行为是保持连接活动并将其释放回基础连接池。

某些内容交付网络建议针对某些类型的状态代码(例如,500内部服务器错误)重新解析DNS。为此,我添加了一个自定义NettyDnsNameResolverDnsCache,但我还需要关闭连接,否则它将被释放回池,并且不会重新解析DNS。

如何在出现错误状态代码时关闭连接?

到目前为止,我已经想出了以下解决方法,将ConnectionObserver添加到反应器Netty的TcpClient

TcpClient tcpClient = TcpClient.create()
        .observe((connection, newState) -> {
            if (newState == State.RELEASED && connection instanceof HttpClientResponse) {
                HttpResponseStatus status = ((HttpClientResponse) connection).status();
                if (status.codeClass() != HttpStatusClass.SUCCESS) {
                    connection.dispose();
                }
            }
        });

即,如果连接已释放(即放回连接池中),并且释放是由状态代码为UNSUCCESS的HTTP客户端响应引起的,则关闭该连接。

这种方法感觉很笨拙。如果在错误状态码之后释放连接,并且观察器正在关闭该连接,则新请求是否可以并行获取相同的连接?框架是否在内部优雅地处理事情,或者这是否是使上述方法无效的争用条件?

提前感谢您的帮助!


解决方案

最好使用doOnResponse或doAfterResponseSuccess,具体取决于哪个用例更合适。

不过,等待释放应该不是问题

如果在错误状态码之后释放连接,而观察者正在关闭该连接,则新请求是否可以并行获取相同的连接?框架是否在内部优雅地处理事情,或者这是否是使上述方法无效的争用条件?

连接池默认运行FIFO租赁策略,如果池中有空闲连接,则不会获得相同的连接,如果将连接池切换为后进先出租赁策略,则不会获得相同的连接。获取时,会检查每个连接是否处于活动状态,并且只提供活动的连接供使用。

更新:

您也可以尝试下面的方法,只使用WebClient API而不使用反应器Netty API:

return this.webClient
           .get()
           .uri("/500")
           .retrieve()
           .onStatus(status -> status.equals(HttpStatus.INTERNAL_SERVER_ERROR), clientResponse -> {
                clientResponse.bodyToFlux(DataBuffer.class)
                              .subscribe(new BaseSubscriber<DataBuffer>() {
                                  @Override
                                  protected void hookOnSubscribe(Subscription subscription) {
                                      subscription.cancel();
                                  }
                              });
                return Mono.error(new IllegalStateException("..."));
           })
           .bodyToMono(String.class);

相关文章