Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VertxHttpClientHTTPConduit-backed client hangs when receiving large responses under load #1613

Closed
ppalaga opened this issue Nov 24, 2024 · 0 comments · Fixed by #1614
Closed

Comments

@ppalaga
Copy link
Contributor

ppalaga commented Nov 24, 2024

This is currently the main hypothesis about the root cause of the second issue reported in #1582

Before Quarkus CXF 3.17.0, the implementation of VertxHttpClientHTTPConduit used a stock java.io pipe to pass the response body data from Vert.x event loop to the worker thread. The pipe was build of PipedOutputStream and PipedInputStream. In situations when Vert.x event loop passed the body data in more than one chunks, the event loop was blocked waiting for the worker thread to drain the fixed size buffer of the pipe. While the Vert.x event loop was blocked, all Vert.x based functionality of the application (other exchanges of the same client, other Vert.x clients, REST endpoints, ...) was hanging. Eventually a warning similar to the following one may have appeared in the log:

2024-11-05 09:24:19,561 WARN  [io.ver.cor.imp.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3809 ms, time limit is 2000 ms: io.vertx.core.VertxException: Thread blocked
	at java.base/java.lang.Object.wait0(Native Method)
	at java.base/java.lang.Object.wait(Object.java:366)
	at java.base/java.io.PipedInputStream.awaitSpace(PipedInputStream.java:279)
	at java.base/java.io.PipedInputStream.receive(PipedInputStream.java:237)
	at java.base/java.io.PipedOutputStream.write(PipedOutputStream.java:154)
	at java.base/java.io.OutputStream.write(OutputStream.java:124)
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyHandler.lambda$pipe$3(VertxHttpClientHTTPConduit.java:694)
	at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:270)
	at io.vertx.core.http.impl.HttpEventHandler.handleChunk(HttpEventHandler.java:51)
	at io.vertx.core.http.impl.HttpClientResponseImpl.handleChunk(HttpClientResponseImpl.java:239)
	at io.vertx.core.http.impl.Http1xClientConnection$StreamImpl.lambda$new$0(Http1xClientConnection.java:429)
	at io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:279)
	at io.vertx.core.streams.impl.InboundBuffer.write(InboundBuffer.java:157)
	at io.vertx.core.http.impl.Http1xClientConnection$StreamImpl.handleChunk(Http1xClientConnection.java:705)
	at io.vertx.core.impl.ContextImpl.execute(ContextImpl.java:313)
	at io.vertx.core.impl.DuplicatedContext.execute(DuplicatedContext.java:159)
	at io.vertx.core.http.impl.Http1xClientConnection.handleResponseChunk(Http1xClientConnection.java:888)
	at io.vertx.core.http.impl.Http1xClientConnection.handleHttpMessage(Http1xClientConnection.java:807)
	at io.vertx.core.http.impl.Http1xClientConnection.handleMessage(Http1xClientConnection.java:774)
	at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:159)
	at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:153)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

In Quarkus CXF 3.17.0, the blocking java.io pipe was replaced by a non-blocking Vert.x pipe with properly implemented back pressure for the case when the worker thread consumes the data more slowly than it is produced by the Vert.x event loop.

ppalaga added a commit to ppalaga/quarkus-cxf that referenced this issue Nov 24, 2024
ppalaga added a commit to ppalaga/quarkus-cxf that referenced this issue Nov 24, 2024
ppalaga added a commit to ppalaga/quarkus-cxf that referenced this issue Nov 24, 2024
ppalaga added a commit to ppalaga/quarkus-cxf that referenced this issue Nov 24, 2024
ppalaga added a commit to ppalaga/quarkus-cxf that referenced this issue Nov 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant