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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:53:02