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

Kubernetes中Spring Boot微服务CPU占用过高问题排查求助

微服务CPU持续100%问题排查需求

环境与问题现象

我们在Kubernetes中部署了约60个微服务,其中两个运行一段时间后出现CPU占用率跳升至100%并持续维持的问题(Pod分配1核新一代AMD EPYC CPU)。问题随机出现在应用启动到人工重启/删除Pod的任意阶段。

这些微服务基于以下技术栈构建:

  • Spring Boot 2.7.8
  • Undertow(替代Tomcat)
  • Retrofit2 2.9.0 + OkHttp3 3.14.9
  • Project Reactor

异常线程转储

捕获到的线程转储显示存在长期存活的异常线程,每次转储时该线程均处于类似状态,存活时长几乎与微服务运行时长一致,栈迹偶尔变化:

"getProductVariants-260" #354 prio=5 os_prio=0 cpu=678915664.69ms elapsed=687202.16s tid=0x00007f63d800a800 nid=0x170 runnable  [0x00007f643ccec000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.Throwable.fillInStackTrace(java.base@11.0.17/Native Method)
        at java.lang.Throwable.fillInStackTrace(java.base@11.0.17/Throwable.java:787)
        - locked <0x00000000f4132990> (a okhttp3.internal.connection.RouteException)
        at java.lang.Throwable.<init>(java.base@11.0.17/Throwable.java:315)
        at java.lang.Exception.<init>(java.base@11.0.17/Exception.java:102)
        at java.lang.RuntimeException.<init>(java.base@11.0.17/RuntimeException.java:96)
        at okhttp3.internal.connection.RouteException.<init>(RouteException.java:31)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.java:96)
        at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:169)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at de.md.services.microframework.http.RetryInterceptor.intercept(RetryInterceptor.java:22)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at de.md.services.microframework.http.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:98)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at de.md.services.microframework.http.HeaderInterceptor.intercept(HeaderInterceptor.java:32)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at de.md.services.microframework.http.RetrofitClient.lambda$buildOkHttpClient$0(RetrofitClient.java:166)
        at de.md.services.microframework.http.RetrofitClient$$Lambda$1044/0x0000000100959c40.intercept(Unknown Source)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229)
        at okhttp3.RealCall.execute(RealCall.java:81)
        at retrofit2.OkHttpCall.execute(OkHttpCall.java:204)
        at com.jakewharton.retrofit2.adapter.reactor.ExecuteSinkConsumer.accept(ExecuteSinkConsumer.java:39)
        at com.jakewharton.retrofit2.adapter.reactor.ExecuteSinkConsumer.accept(ExecuteSinkConsumer.java:24)
        at reactor.core.publisher.FluxCreate.subscribe(FluxCreate.java:95)
        at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194)
        at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84)
        at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37)
        at java.util.concurrent.FutureTask.run(java.base@11.0.17/FutureTask.java:264)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(java.base@11.0.17/ScheduledThreadPoolExecutor.java:304)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.17/ThreadPoolExecutor.java:1128)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.17/ThreadPoolExecutor.java:628)
        at java.lang.Thread.run(java.base@11.0.17/Thread.java:829)

相关业务代码

涉及的getProductVariants方法实现如下:

public Mono<ProductVariantList> getProductVariants(String productVariantIds, HttpServletRequest httpServletRequest) {
        ProductConnector productConnector = retrofitClient.buildRetrofitClientReactorDefault(
                connectorConfig.getProductService(), connectorConfig.getDefaultTimeout(), getProductVariantsScheduler,
                httpServletRequest).create(ProductConnector.class);
        return productConnector.getProductVariants(productVariantIds, connectorConfig.getSlapToken()) //
                .doOnNext(res -> ThirdPartyUtils.checkRetrofitResponse(res, LOGGER, "ProductService"))
                .flatMap(MonoHelper::toResponseContentMono) //
                .doOnError(error -> LOGGER.error("getProductVariants ist auf einen Fehler gelaufen.", error));
    }

补充配置信息:

  • 默认请求超时10秒
  • getProductVariantsScheduler为Project Reactor调度器,线程上限40,队列上限100000
  • 该请求仅从第三方微服务获取小于150KB的数据
  • 服务请求量约10-20次/分钟,部署两个实例
  • 内存消耗及内存转储均无异常

排查思路

  • OkHttp版本BUG验证:OkHttp 3.14.9存在连接池相关的高CPU/死循环已知问题,结合线程栈卡在RouteException创建环节,优先升级到3.14.x最新补丁版(如3.14.12),确认是否解决问题。
  • 自定义RetryInterceptor逻辑检查:检查自定义重试拦截器是否存在无限循环——比如未设置重试次数上限,或错误码判断逻辑导致持续重试,进而触发OkHttp内部异常处理的循环消耗。
  • Reactor调度器配置校验:验证getProductVariantsScheduler的任务超时、拒绝策略是否生效,是否存在任务堆积导致线程长期占用CPU;确认subscribeOn的使用是否正确,避免线程泄漏。
  • OkHttp连接池配置优化:检查连接池的maxIdleConnections、keepAliveDuration配置,是否存在闲置连接未回收导致的线程泄漏;尝试调整连接池参数,观察CPU占用变化。
  • 异常栈轨迹填充优化:线程栈显示卡在Throwable.fillInStackTrace(Native方法),若频繁触发会导致高CPU。排查RouteException高频抛出的根源(如网络波动、DNS异常),或通过升级OkHttp减少不必要的栈轨迹填充。
  • 超时逻辑有效性验证:确认OkHttp的超时配置是否正确传递到请求,检查自定义拦截器是否覆盖了超时设置;验证Reactor适配器的超时与OkHttp超时是否存在冲突,确保超时能正常触发终止请求。
  • AMD EPYC架构适配检查:JDK 11.0.17在AMD EPYC架构下可能存在性能异常,尝试升级到11.0.x最新补丁版,或调整JVM参数(如GC策略、线程数)优化CPU使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:31:03