如何在JVM中禁用JMX/MBeans解决Debezium连接器注册异常
我有两个Debezium SQL Server连接器,需要连接同一数据库并同步不同表。它们的name和database.history.kafka.topic都设置为唯一值,但添加第二个连接器(通过POST请求)时触发了如下异常:
java.lang.RuntimeException: Unable to register the MBean 'debezium.sql_server:type=connector-metrics,context=schema-history,server=mydatabase' Caused by: javax.management.InstanceAlreadyExistsException: debezium.sql_server:type=connector-metrics,context=schema-history,server=mydatabase
我不想给database.server.name设置唯一值(这个参数被反直觉地用作指标名称)。我们完全用不到JMX/MBeans,所以想禁用它,但不知道怎么操作。如果有JVM层面的通用方法也请告知。
另外我看到了Debezium中注册MBean的代码,仅看前两行的逻辑,似乎让ManagementFactory.getPlatformMBeanServer()返回null就能解决问题。所以另一个问法是:怎么强制让ManagementFactory.getPlatformMBeanServer()返回null?
Debezium注册MBean的核心代码如下:
public synchronized void register() { try { final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); if (mBeanServer == null) { LOGGER.info("JMX not supported, bean '{}' not registered", name); return; } // During connector restarts it is possible that Kafka Connect does not manage // the lifecycle perfectly. In that case it is possible the old metric MBean is still present. // There will be multiple attempts executed to register new MBean. for (int attempt = 1; attempt <= REGISTRATION_RETRIES; attempt++) { try { mBeanServer.registerMBean(this, name); break; } catch (InstanceAlreadyExistsException e) { if (attempt < REGISTRATION_RETRIES) { LOGGER.warn( "Unable to register metrics as an old set with the same name exists, retrying in {} (attempt {} out of {})", REGISTRATION_RETRY_DELAY, attempt, REGISTRATION_RETRIES); final Metronome metronome = Metronome.sleeper(REGISTRATION_RETRY_DELAY, Clock.system()); metronome.pause(); } else { LOGGER.error("Failed to register metrics MBean, metrics will not be available"); } } } // If the old metrics MBean is present then the connector will try to unregister it // upon shutdown. registered = true; } catch (JMException | InterruptedException e) { throw new RuntimeException("Unable to register the MBean '" + name + "'", e); } }
方法1:通过Debezium连接器配置禁用JMX指标
在每个连接器的配置中添加以下参数,直接跳过所有指标(包括JMX MBean)的注册:
metrics.enabled=false
这个配置从连接器层面禁用指标功能,彻底避免MBean名称冲突的问题,是最直接的解决方案。
方法2:JVM层面禁用Platform MBean Server
如果需要全局禁用JMX,或者连接器配置无法生效,可以通过JVM启动参数替换默认的MBeanServer工厂,让ManagementFactory.getPlatformMBeanServer()返回null:
HotSpot JVM(OpenJDK/Oracle JDK)
添加以下启动参数:
-Djava.lang.management.ManagementFactory=com.sun.management.internal.NoPlatformMBeanServerFactory
OpenJ9 JVM
使用以下参数:
-Dcom.ibm.lang.management.disablePlatformMBeanServer=true
这样Debezium的代码会检测到MBeanServer为null,自动跳过MBean注册流程,不会再抛出异常。
内容的提问来源于stack exchange,提问作者Delphi.Boy

