Spring 启动 WebClient 连接由于 io.netty.handler.codec.TooLongFrameException 而被冻结:HTTP 标头大于 8192 字节

问题描述 投票:0回答:1

我正在使用 webclient 连接到下游 API,在收到下游的响应后,我的服务会抛出一条 warning 消息,如下所示:

2024-05-01 20:04:08,240 [reactor-http-nio-1] traceId:[] **WARN**  r.n.http.client.HttpClientConnect#299 -> [id: 0x7fa2c1c0, L:/127.0.0.1:55568 - R:localhost/127.0.0.1:3000] The connection observed an error
io.netty.handler.codec.TooLongFrameException: HTTP header is larger than 8192 bytes.
    at io.netty.handler.codec.http.HttpObjectDecoder$HeaderParser.newException(HttpObjectDecoder.java:951)
    at io.netty.handler.codec.http.HttpObjectDecoder$HeaderParser.increaseCount(HttpObjectDecoder.java:946)
    at io.netty.handler.codec.http.HttpObjectDecoder$HeaderParser.process(HttpObjectDecoder.java:934)
    at io.netty.buffer.AbstractByteBuf.forEachByteAsc0(AbstractByteBuf.java:1301)
    at io.netty.buffer.AbstractByteBuf.forEachByte(AbstractByteBuf.java:1281)
    at io.netty.handler.codec.http.HttpObjectDecoder$HeaderParser.parse(HttpObjectDecoder.java:908)
    at io.netty.handler.codec.http.HttpObjectDecoder.readHeaders(HttpObjectDecoder.java:593)
    at io.netty.handler.codec.http.HttpObjectDecoder.decode(HttpObjectDecoder.java:255)
    at io.netty.handler.codec.http.HttpClientCodec$Decoder.decode(HttpClientCodec.java:225)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)

此错误作为 警告 出现,但在对同一 url 端点的后续调用中,Web 客户端连接池耗尽,我得到

org.springframework.web.reactive.function.client.WebClientRequestException: Pool#acquire(Duration) has been pending for more than t
he configured timeout of 45000ms;

注意:上述标头异常正在被捕获并进行相应处理。

后续所有对下游的调用都无法连接,并出现上述超时异常。

**我认为这个连接池耗尽是由于在上述大标头警告之后连接仍然没有释放。 **

在我的配置文件中为 webClient 创建 bean 时,我已使用给定方法将响应标头的标头大小增加到 100kb。

httpResponseDecoder(res -> res.maxHeaderSize(maxHeaderSize));

这暂时解决了我的问题。

但我仍然不确定为什么大标头警告会耗尽 webClient 连接池中的连接。

我假设上述理论:**此连接池耗尽是由于在上述大标头警告之后连接仍未释放。 **

有什么方法可以在一段时间后关闭或释放在Web客户端中获取的连接,或者我们是否可以为其配置任何超时。

我们可以通过从mockoon发送一个大的响应头(大小大于8192个字符)来重现这个问题。或者使用上述解决方案减少 macHeaderSize。

java spring-boot rest httpclient webclient
1个回答
0
投票

有一种方法可以设置 Web 客户端连接的超时。尝试一下。

 WebClient client = WebClient.create();
    client.get()
            .uri("/someURL")
            .retrieve()
            .bodyToFlux(Object.class)
            .timeout(Duration.ofMillis(10_000));
© www.soinside.com 2019 - 2024. All rights reserved.