记一次springJmx发布服务,但是订阅不到消息的问题

将spring的bean暴露给jmx服务,我们可以通过jconsole去连接,可以很方便的看到bean的情况。jmx也可以发布通知,在jconsole订阅对应的MBean就可以看到发布的消息,从而实现监控的功能。

开启jmx服务
在这里插入图片描述
将bean暴露给jmxserver
在这里插入图片描述
想实现jmx的发布通知功能,实现NotificationPublisherAware接口,实现sendNotificationPulisher方法,并在方法内部使用一个变量接收sendNotificationPulisher就可以使用该变量来发布通知了。sendNotificationPulisher()方法在spring容器初始化的时候自动调用。

接下来就是项目启动的时候需要加入一些参数,如下
-Dcom.sun.management.jmxremote.port=1090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

启动项目,使用jconsole工具去连接,然后订阅通知。此时就遇到了一个问题,debug模式下分明看到消息是有发布出去的,但是在通知缓冲区就是没有收到。折腾了好久,排查了jdk和spring的版本的问题。最后排查到这行代码

在这里插入图片描述
这里在创建tomcat实例的时候,把sprng容器的ApplicationContext设置进去。在设置之前做了一个refresh的操作。刷新了一下ApplicationContext。刷新容器这个操作会使重新注册一遍Mbean,也会重新执行NotificationPublisherAware.sendNotificationPulisher(notificationPulisher),导致notificationPulisher这个对象发生了变化,但是在DefaultMBeanServerInterceptor中repository的notificationPulisher没有被重置。

也就是说保存在jmxserver仓库中的MBean有一个对应的notificationPulisher对象,这个是第一次初始化创建的;而容器refresh没有更新到jmxserver仓库中的notificationPulisher对象,导致注册监听的notificationPulisher和发布通知的notificationPulisher不是同一个bean。所以接收不到通知。

小知识点:当我们使用jconsole去连接jmx服务的时候,jmx中的MBean都会注册一个默认的监听器,发布的通知都会在默认监听器上接收到,这个默认监听器也就是jconsole工具上使用的监听器。

解决办法有两个
1、注入notificationPulisher对象的,做一下null值判断,这样就保证只在第一次初始化的时候会赋值
在这里插入图片描述
2、spring容器不需要刷新,可以直接使用,把刷新操作注释掉

// wrapper.refresh();

到此问题解决,折腾了好久才排查到这个问题,对spring还是太不熟悉了,继续加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值