Quarkus(Mutiny+Vert.x)部署在GCP Cloud Run后,并发调用多API出现Vert.x线程阻塞及疑似线程泄漏问题求助
Quarkus(Mutiny+Vert.x)部署在GCP Cloud Run后,并发调用多API出现Vert.x线程阻塞及疑似线程泄漏问题求助
大家好,我最近碰到一个特别棘手的问题:本地开发测试完全正常,但部署到Google Cloud Run后就出现了Vert.x线程阻塞,还疑似有线程泄漏的情况,想请各位大佬帮忙分析下!
问题背景
我开发了一个小型Demo应用,用来复现并修复我们大型项目里的性能问题。这个服务需要实现fire-and-forget的逻辑:接收一个字符串,解析后调用两个独立的远程API获取数据,之后用MapStruct做对象映射。本地在IntelliJ中运行时,所有请求都能瞬间响应,完全没问题;但部署到Google Cloud Run后,很快就出现了Vert.x线程阻塞的警告,服务性能急剧下降,看起来像是线程泄漏了。
核心代码片段
Controller层
import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.UUID; // 省略其他无关代码 @POST @Path("/test") @Consumes(MediaType.APPLICATION_JSON) public Uni<Response> sendInfologOrderReleaseTest(Apin2Request message) throws InterruptedException { infologOrderReleaseService.test(message.getContent()) .subscribe() .with( result -> { }, // 忽略成功结果 failure -> log.error("Fire-and-forget failed", failure) ); return Uni.createFrom().item(Response.accepted().build()); }
Service层
import io.smallrye.mutiny.Uni; import jakarta.ws.rs.core.Response; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; // 省略其他无关代码 public Uni<OrderReleaseDto> test(String content) { log.info("starting test"); Uni<List<SiteDTO>> sourceSiteUni = testClient.getFilteredRdoSiteTransco(); Uni<List<SiteDTO>> destinationSiteUni = testClient.getFilteredRdoSiteTransco(); return Uni.combine().all().unis(sourceSiteUni, destinationSiteUni) .with((source, destination) -> { log.info("starting mapping for source: {}, destination: {}", source.size(), destination.size()); log.info("end mapping"); return OrderReleaseDto.builder().build(); }); }
Rest Client接口
import io.smallrye.mutiny.Uni; import jakarta.enterprise.inject.Default; import jakarta.ws.rs.GET; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import java.util.List; @Default @RegisterRestClient(configKey = "rdo-site-transco") public interface TestClient { @GET Uni<List<SiteDTO>> getFilteredRdoSiteTransco(); }
部署到Cloud Run后的错误日志
2025-07-21 20:28:46.382 HAEC 2025-07-21 18:28:46,182 WARN [io.ver.cor.imp.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-eventloop-thread-1,5,main] has been blocked for 10594 ms, time limit is 2000 ms: io.vertx.core.VertxException: Thread blocked 2025-07-21 20:28:46.383 HAEC at java.base/java.io.RandomAccessFile.readBytes0(Native Method) 2025-07-21 20:28:46.383 HAEC at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java:400) 2025-07-21 20:28:46.383 HAEC at java.base/java.io.RandomAccessFile.read(RandomAccessFile.java:434) 2025-07-21 20:28:46.383 HAEC at java.base/java.io.RandomAccessFile.readFully(RandomAccessFile.java:498) 2025-07-21 20:28:46.383 HAEC at java.base/java.util.zip.ZipFile$Source.readFullyAt(ZipFile.java:1528) 2025-07-21 20:28:46.383 HAEC at java.base/java.util.zip.ZipFile$ZipFileInputStream.initDataOffset(ZipFile.java:930) 2025-07-21 20:28:46.383 HAEC at java.base/java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:946) 2025-07-21 20:28:46.383 HAEC at java.base/java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:463) 2025-07-21 20:28:46.383 HAEC at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:175) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.JarResource$JarResourceDataProvider.apply(JarResource.java:73) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.JarResource$JarResourceDataProvider.apply(JarResource.java:59) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.JarFileReference.consumeSharedJarFile(JarFileReference.java:169) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.JarFileReference.withJarFile(JarFileReference.java:135) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.JarResource.getResourceData(JarResource.java:56) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:106) 2025-07-21 20:28:46.383 HAEC at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:72) 2025-07-21 20:28:46.383 HAEC at io.netty.handler.ssl.SslHandler$SslEngineType.forEngine(SslHandler.java:360) 2025-07-21 20:28:46.383 HAEC at io.netty.handler.ssl.SslHandler.<init>(SslHandler.java:480) 2025-07-21 20:28:46.383 HAEC at io.netty.handler.ssl.SslContext.newHandler(SslContext.java:1076) 2025-07-21 20:28:46.383 HAEC at io.netty.handler.ssl.DelegatingSslContext.newHandler(DelegatingSslContext.java:100) 2025-07-21 20:28:46.383 HAEC at io.netty.handler.ssl.SslContext.newHandler(...)
我的困惑与求助
从日志来看,线程阻塞发生在类加载和SSL相关的操作上,但本地完全没这个问题。我怀疑是不是Cloud Run的环境和本地有什么差异?或者我的Mutiny异步调用写法有问题?有没有大佬遇到过类似的情况,或者能给我一些排查方向、解决思路?
内容来源于stack exchange
相关产品推荐
相关产品推荐

