鲲鹏社区首页
中文
注册
Java应用迁移至CCE容器异常问题优化分析

Java应用迁移至CCE容器异常问题优化分析

案例分享

发表于 2025/09/12

0

作者|薛大量

环境信息

服务器型号

TaiShan 200 (Model 2280)

操作系统

EulerOS 2.8

容器镜像

Kylin V10 SP2

软件

Netty 4.1.72.final

OpenJDK 1.8.0_242 (上游来源为openEuler社区)

JCTools 3.1.0

故障分析

BMC日志分析

  • sel日志主要记录服务器事件打印,近期无硬件故障事件打印(重启时间2022年11月4日)。

  • fdm日志主要记录服务器硬件故障打印,近期无硬件故障。

硬件分析总结:服务器硬件正常,无异常告警。

Netty应用分析

  • 堆栈分析
    使用jstack工具分析Netty应用运行出现异常时的堆栈,抓取内存的Dump包,存在死循环线程堆栈的情况。MpscChunkedArrayQueue::poll函数存在死循环,导致应用运行一直停留在该函数,死循环不停占用CPU资源,最终导致CPU资源被占满,容器hang死,应用异常。
    业务应用主要调用Netty的无锁队列BaseMpscLinkedArrayQueue.java,分析源码得知无锁队列消费者在调用poll函数去获取元素时进入了死循环。

  • 排查buglist
    排查Netty上游社区的buglist,上游社区曾提出相似的问题,相关buglist如下:
    https://github.com/netty/netty/issues/11956
    https://github.com/netty/netty/issues/13137
    https://github.com/netty/netty/pull/11972
    https://github.com/netty/netty/pull/12495
    https://github.com/netty/netty/pull/10855
    Netty在高版本中新创建了一个阻塞队列BlockingMessageQueue.java,通过设置开关“-Dio.netty.recycler.blocking=true”可以使用 BlockingMessageQueue 替代 MpscChunkedArrayQueue,避免进入死循环。
  • Netty应用分析总结
    Netty应用执行时进入死循环导致出现问题,死循环的原因需要通过java heapdump日志进一步分析,建议客户将测试环境的Netty版本升级到4.1.73,设置开关“-Dio.netty.recycler.blocking=true”使用有锁队列,进行充分测试验证后再上线到业务环境。

OpenJDK分析

OpenJDK分析使用jmap工具导出java heapdump日志进行分析,消费者MpscChunkedArrayQueue的两个无锁队列对象中存在大量的空元素,确认是消费者通过poll函数去获取队列元素时因为元素为空导致死循环。

排查OpenJDK上游社区的buglist,上游社区曾提出相似的问题,相关buglist如下:
https://bugs.openjdk.org/browse/JDK-8209420
https://bugs.openjdk.org/browse/JDK-8179954
客户使用的OpenJDK为麒麟提供,上游来源为openEuler社区,分析社区仓库的源码信息,242低版本源码和OpenJDK社区基本一致,通过OpenJDK的buglist可以确认低版本存在锁实现相关的缺陷,这些缺陷在高版本中已进行修复。
OpenJDK 1.8在242版本时已经进入维护期,主要进行bug修复和CVE修复。当前OpenJDK 1.8最新版本为362,分析OpenJDK 从242到362版本的release note,有50+的CVE修复合入,从安全方面进行分析,使用低版本有安全风险,建议升级OpenJDK版本。
OpenJDK官网发布的release note地址:https://wiki.openjdk.org/display/jdk8u/Main
OpenJDK分析总结:
OpenJDK 1.8低版本存在锁相关实现的缺陷,这些缺陷在高版本中已修复,并且低版本存在安全风险,建议客户将测试环境的OpenJDK 1.8升级至最新版本,进行充分验证测试后再上线到业务环境。

根因分析及措施

根因分析

  1. Netty低版本无锁队列MpscChunkedArrayQueue,当消费者无锁队列中存在空元素时会进入死循环;

  2. OpenJDK 1.8低版本锁相关实现存在缺陷,这些缺陷在高版本中已修复。

建议措施

根据以下建议,进行充分验证测试后再上线到业务环境。

  1. 将Netty版本升级到4.1.73版本,并添加配置项“-Dio.netty.recycler.blocking=true”以使用有锁队列;

  2. 将OpenJDK 1.8升级到最新版本。