You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus Vertx构建后首次7MB流API调用连接超时问题

首次大流量(7MB)API调用失败,后续正常的排查与解决

问题现象

当请求输入流大小为7MB时,服务构建完成后的首次API调用必定失败,后续所有调用均可正常执行。失败时抛出连接关闭异常,完整栈日志如下:

2023-12-18 23:18:11,768 WARNING 23 [com.log.cor.jax.imp.exc.map.BaseExceptionMapper] (50740c4dfeb9df41) createResponse(Throwable): java.io.IOException: java.io.IOException: io.vertx.core.http.HttpClosedException: Connection was closed
at io.quarkus.vertx.http.runtime.VertxInputStream$VertxBlockingInput.readBlocking(VertxInputStream.java:255)
at io.quarkus.vertx.http.runtime.VertxInputStream.readIntoBuffer(VertxInputStream.java:122)
at io.quarkus.vertx.http.runtime.VertxInputStream.read(VertxInputStream.java:84)
at java.base/java.io.SequenceInputStream.read(SequenceInputStream.java:199)
at org.apache.james.mime4j.io.BufferedLineReaderInputStream.fillBuffer(BufferedLineReaderInputStream.java:111)
at org.apache.james.mime4j.io.MimeBoundaryInputStream.fillBuffer(MimeBoundaryInputStream.java:223)
at org.apache.james.mime4j.io.MimeBoundaryInputStream.read(MimeBoundaryInputStream.java:157)
at org.apache.james.mime4j.io.BufferedLineReaderInputStream.fillBuffer(BufferedLineReaderInputStream.java:111)
at org.apache.james.mime4j.io.BufferedLineReaderInputStream.read(BufferedLineReaderInputStream.java:158)
at org.apache.james.mime4j.io.LineReaderInputStreamAdaptor.read(LineReaderInputStreamAdaptor.java:67)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.james.mime4j.util.ContentUtil.copy(ContentUtil.java:55)
at org.apache.james.mime4j.storage.AbstractStorageProvider.store(AbstractStorageProvider.java:57)
at org.apache.james.mime4j.storage.StorageBodyFactory.binaryBody(StorageBodyFactory.java:94)
at org.jboss.resteasy.plugins.providers.multipart.Mime4jWorkaroundBinaryEntityBuilder.body(Mime4jWorkaroundBinaryEntityBuilder.java:159)
at org.apache.james.mime4j.parser.MimeStreamParser.parse(MimeStreamParser.java:133)
at org.jboss.resteasy.plugins.providers.multipart.Mime4JWorkaround.parseMessage(Mime4JWorkaround.java:83)
at org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl.parse(MultipartInputImpl.java:104)
at org.jboss.resteasy.plugins.providers.multipart.MultipartFormAnnotationReader.readFrom(MultipartFormAnnotationReader.java:58)
at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:101)
at org.jboss.resteasy.core.interception.jaxrs.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:63)
at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:80)
at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:213)
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:95)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:128)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:82)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:147)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:93)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.io.IOException: io.vertx.core.http.HttpClosedException: Connection was closed   

已尝试调整Vertx相关配置,但问题未解决。

可能原因分析

  1. 组件预热不足:Quarkus+Vertx架构下,首次处理大流量请求时,HTTP连接池、请求缓冲区、Multipart解析器等组件未完成初始化,导致读取请求体过程中连接被提前关闭
  2. 超时配置不匹配:默认的请求体读取超时时间过短,首次调用时组件初始化耗时叠加请求处理时间,触发超时
  3. Multipart解析器初始化延迟:日志中涉及的Mime4J解析组件首次加载时,类初始化、资源准备耗时过长,导致连接在解析完成前被关闭

解决方案

1. 添加服务启动预热逻辑

在服务启动完成后,主动发起一个小流量请求,触发所有核心组件初始化:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import io.quarkus.runtime.StartupEvent;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;

@ApplicationScoped
public class ApiWarmer {
    void onStartup(@Observes StartupEvent event) {
        // 发起简单的预热请求,路径替换为你的健康检查或轻量接口
        Client client = ClientBuilder.newClient();
        client.target("http://localhost:8080/health").request().get();
        client.close();
    }
}

2. 调整Vertx HTTP核心配置

在application.properties中添加以下配置,延长超时时间并优化缓冲区:

# 延长请求体读取超时时间
quarkus.vertx.http.read-timeout=30s
# 增大请求体大小限制
quarkus.vertx.http.body-limit=32MB
# 调整HTTP块大小,适配大流量请求
quarkus.vertx.http.max-chunk-size=16MB
# 优化连接池参数,加快预热速度
quarkus.vertx.http.pool.max-size=20
quarkus.vertx.http.pool.cleaner-period=5s

3. 提前加载核心解析类

配置Quarkus提前加载Multipart相关解析类,避免首次调用时的初始化延迟:

quarkus.arc.preloaded-classes=org.jboss.resteasy.plugins.providers.multipart.Mime4JWorkaround,org.apache.james.mime4j.parser.MimeStreamParser

内容的提问来源于stack exchange,提问作者Akanksha Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 07:20:24