当前位置: 首页 > 知识库问答 >
问题:

使用Http/2时,反应器Netty客户端ReadTimeoutException导致过早关闭异常

焦正德
2023-03-14

我正在使用reamer-netty客户端并通过alpn设置超文本传输协议/2。当我通过. doOnConnect(...)挂钩设置ReadTimeoutHandler时,我最终会得到这个异常:

Jan 09, 2021 6:40:35 PM io.netty.channel.DefaultChannelPipeline onUnhandledInboundException
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.timeout.ReadTimeoutException

这似乎是良性的,响应很好,所以我真的不确定那里发生了什么,但当我开始努力驱动我的客户机时,尤其是使用gatling时,我开始看到通过PrematureCloseException的失败响应,这在生产环境中是不可接受的。只要我删除ReadTimeoutHandler,这种行为就会消失。

我不确定这里发生了什么,也不确定是否由于Http/2的原因,我的设置不正确。据我所知,这是扩展客户端和设置ReadTimeoutHandler的推荐方法。这在Http/1.1上运行得很好,我不确定Http/2上有什么变化。

下面是如何设置客户端来重现它的再现——只需使用此客户端来访问您最喜欢的超文本传输协议/2endpoint。

我正在使用projectreactor bom版本2020.0.2


public static HttpClient createClient() {

final String[] alpnProtocols =
                new String[]{ApplicationProtocolNames.HTTP_2};
        // if the application protocol is set to null the netty code will set it to
        // JdkDefaultApplicationProtocolNegotiator.INSTANCE (which is package protected)
        final ApplicationProtocolConfig APPLICATION_PROTOCOL_CONFIG =
                new ApplicationProtocolConfig(
                        ApplicationProtocolConfig.Protocol.ALPN,
                        // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
                        ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
                        // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
                        ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,
                        alpnProtocols);
        final String[] SUPPORTED_PROTOCOLS =
                new String[]{"TLSv1.3"}; // note that http/2 only works with TLSv1.3 or TLSv1.2

        // a null for non http/2 will result in the default cipher suites for http1.1
        final List<String> CIPHER_SUITES =
                Arrays.asList(new String[]{ "TLS_AES_256_GCM_SHA384" });


        try {
            System.setProperty("io.netty.handler.ssl.noOpenSsl", "false"); // lazy way to set this up

            SslContext sslContext = SslContextBuilder
                    .forClient()
                    .sslProvider(io.netty.handler.ssl.SslProvider.OPENSSL)
                    .ciphers(CIPHER_SUITES)
                    .applicationProtocolConfig(APPLICATION_PROTOCOL_CONFIG)
                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                    .protocols(SUPPORTED_PROTOCOLS)
                    .build();


            return HttpClient.create()
                    .port(3443)
                    .baseUrl("https://localhost")
                    .secure(spec -> spec.sslContext(sslContext))
                    .protocol(HttpProtocol.H2)
                    .doOnConnected(con -> con.addHandlerLast(
                            new ReadTimeoutHandler(4_500, TimeUnit.MILLISECONDS)));


        } catch (Exception e) {
            throw new RuntimeException(e);
        }

共有1个答案

颛孙晗昱
2023-03-14

PrematureCloseException是当Gatling尝试在其上写入时连接被远程对等方关闭时得到的结果。当重用池化的保活连接时,这是一种完全正常的情况,因为网络不是即时的。

旧版本的Gatling不能完美地处理这种情况。如果您使用的是旧版本,您应该升级(目前最新的版本是3.5.0)。

 类似资料:
  • 我正在尝试在Netty中开始使用HTTP/2。我尝试了“hello world”示例,它按预期工作。在示例中,管道如下所示: 服务器: SslHandler 应用程序协议协商处理程序 Http2ConnectionHandler 客户: SslHandler 应用程序协议协商处理程序 HttpToHttp2ConnectionHandler

  • 我正在关注Quarkus-反应指南入门,并在使用服务器发送的事件的示例中与ClosedChannel异常进行斗争。resteasy资源处理程序使用vert。引擎盖下的x和netty以及反应流的SmallRye Mutiny库。 资源处理程序以1秒的间隔生成count条消息。 消息会根据请求发送到客户端。客户端是嵌入到html页面中的简单javascript函数: 在客户端,所有工作都按预期进行。事

  • 我对netty比较陌生,不确定自己做的事情是否正确。我会尽量短一点。如果有任何不清楚的地方,请询问更多信息。 因此,我有一个提供HTTP请求的netty服务器,其中的内容应该是序列化为Json字符串的protobuf消息。 通道管道如下所示: 前两个通道处理程序是标准的netty工具, HttpProtobufServerCodec类似于: 和HttpToProtobufDecoder类似于: 因

  • 我使用请求一组URL。大多数URL属于相同的主机。似乎会为每个URL创建一个全新的TCP连接,即使已经为上一个URL建立了到主机的连接。当数百个连接同时建立时,一些服务器会丢弃新的连接或开始缓慢响应。 代码示例: 在日志中,我看到同一个远程主机的本地端口不同,活动和非活动连接的总和远远高于不同主机的数量。这就是为什么我认为没有重用已经建立的连接。 是否可以使用HTTP客户端通过与主机的同一TCP连

  • 我正在使用创建。jar文件。它位于下 然后,创建一个简单的,如下所示: 构建docker映像:

  • 如何在基于网络的 HTTP 客户端中重试 HTTP 请求? 请考虑以下处理程序,如果收到 HTTP 响应代码 503,它将尝试在 1 秒后重试 HTTP 请求: 在本例中,当我写入通道时,管道中的其他处理程序会看到HttpObjects,但实际上不会再次执行HttpRequest——只接收到一个HttpResponse。 我认为在这种情况下我只是滥用了 Channel,我需要创建一个新的通道(表示