Confluent Kafka Connect镜像加载JMX Exporter报NoSuchFieldError异常
Kafka Connect JMX Exporter启动NoSuchFieldError排查方案
问题场景
尝试暴露Kafka Connect Worker的JMX监控指标,使用如下Dockerfile构建自定义镜像:
FROM cnfldemos/cp-server-connect-datagen:0.5.3-7.1.0 ADD --chown=1000:1000 exporterConfig.yml /opt/prometheus-exporter/prom-jmx-agent-config.yml ADD --chown=1000:1000 jmx_prometheus_javaagent-0.17.0.jar /opt/prometheus-exporter/agent.jar
使用的JMX Exporter为0.x分支版本0.17.0,Connect Worker启动时抛出如下错误日志:
PS D:\env\confluent-platform> docker logs connect -f ===> User uid=1000(appuser) gid=1000(appuser) groups=1000(appuser) ===> Configuring ... ===> Running preflight checks ... ===> Check if Kafka is healthy ... Exception in thread "main" java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:513) at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:525) Caused by: java.lang.NoSuchFieldError: UNKNOWN at io.prometheus.jmx.JmxCollector$Rule.<init>(JmxCollector.java:57) at io.prometheus.jmx.JmxCollector.loadConfig(JmxCollector.java:214) at io.prometheus.jmx.JmxCollector.<init>(JmxCollector.java:91) at io.prometheus.jmx.JavaAgent.premain(JavaAgent.java:29) ... 6 more *** java.lang.instrument ASSERTION FAILED ***: "result" with message agent load/premain call failed at src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 422 FATAL ERROR in native method: processing of -javaagent failed, processJavaStart failed
根因定位
抛出的java.lang.NoSuchFieldError: UNKNOWN属于典型的类加载版本冲突问题:
- JMX Exporter 0.17.0内置依赖0.14版本的simpleclient,该版本
Collector.java类中新增了UNKNOWN枚举值 - 在
cnfldemos/cp-server-connect-datagen镜像构建源码中找不到相关依赖引用,是因为旧版simpleclient包来自该镜像的多层父基础镜像(Confluent官方cp-base镜像会在监控组件目录预置低版本simpleclient),这些路径默认被加入JVM启动类路径,且加载优先级高于javaagent内部打包的依赖类,导致JMX Exporter初始化时加载到旧版本类,触发字段不存在错误。
解决方法
任选以下一种方案即可修复问题:
- 方案一:降级JMX Exporter版本
将引入的JMX Exporter替换为0.16.1版本,该版本兼容simpleclient 0.10以下版本的类定义,不会触发枚举字段缺失错误,是成本最低的修复方式。 - 方案二:替换镜像内置旧版依赖
在Dockerfile中增加构建步骤,扫描删除类路径下所有旧版本simpleclient包,替换为0.14版本对应jar包,确保JVM加载的依赖版本和JMX Exporter要求一致。 - 方案三:调整JVM类加载优先级
在Connect服务的KAFKA_OPTS启动参数中,增加bootclasspath配置将agent jar包加入启动类加载路径,优先加载agent内部打包的依赖类,配置示例:KAFKA_OPTS="-Xbootclasspath/a:/opt/prometheus-exporter/agent.jar -javaagent:/opt/prometheus-exporter/agent.jar=9404:/opt/prometheus-exporter/prom-jmx-agent-config.yml"
注意:使用方案三前需确认你使用的JMX Exporter jar包已经shade了全部内置依赖,否则会触发其他类找不到的错误。
内容的提问来源于stack exchange,提问作者Sid
相关产品推荐
相关产品推荐

