ActiveMQ中断(RuntimeTestEvaluator.visit(ShadowMatchImpl.java:140))

本文描述了一次因MQ中断导致业务流程停滞的紧急故障处理过程。通过对MQ配置、业务代码和Spring框架问题的分析,逐步定位到了问题所在,并最终通过代码优化解决了问题。

场景描述

       临下班时,突然接到电话。说某个客户的生产环境上,MQ中断,不能再接收数据,导致整个业务流程中断。由于临下班本来就是一个业务操作的高峰期,造成大面积的客户,门店等待。

       通过了解情况,客户环境通过MQ进行消息中转,解决核心业务系统与我方系统的解藕。我方系统为四个tomcat的集群。

       查看MQ的console,消息量一直在持续增加,其他的消息目标仍有消费者。由此推出MQ服务器本身应该没有问题。

       根据前方的同事的反馈,重启业务系统,MQ上仍然没有消费者。同时反馈中,数据库上有死锁。日志上有标题上的空指针异常。详细如下:

 

java.lang.NullPointerException
	at org.aspectj.weaver.reflect.ShadowMatchImpl$RuntimeTestEvaluator.visit(ShadowMatchImpl.java:140)
	at org.aspectj.weaver.ast.Instanceof.accept(Instanceof.java:29)
	at org.aspectj.weaver.reflect.ShadowMatchImpl$RuntimeTestEvaluator.matches(ShadowMatchImpl.java:121)
	at org.aspectj.weaver.reflect.ShadowMatchImpl.matchesJoinPoint(ShadowMatchImpl.java:78)
	at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:313)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:159)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at $Proxy24.save(Unknown Source)

 

 

        于是乎,怀疑解决死锁是因为有四台同时接收MQ消息。于是关掉三台业务系统的MQ接收,同时在去掉死锁后,重启业务系统,发布可以正常接收MQ消息了。虽然不能理解数据库的死锁跟MQ的中断有什么关系。同时,日志中的NullpointException又有什么关系?

         正当高兴问题已经解决时,前方又反馈MQ上对应的消费者又丢失了。

         于是按日志上的NullpointException去google了一下。这个明显是spring内部的问题,会跟数据有关系吗?

         打到以下bug记录(https://bugs.eclipse.org/bugs/show_bug.cgi?id=318899)。即在spring2.5对应的切面实现中,aspectj对函数第一个参数为空值的情况有bug。会抛出上面提到的异常。顺势查找接口代码,对于外部消息的主键查找本地记录时,没有判断是否存在,都进行save操作。添加判断后,此问题解决。

 

还原错误过程

        一、首先系统MQ接收接口编写不严谨。

                1、没有使用连接池(PooledConnectionFactory)。这样,接收过程由于网络或其他原因中断连接后,不能再重新连接MQ服务器,建立消费者关系。

                2、消息接收自动AUTO_ACK模式,于是接收过程有异常情况,不能正常处理消息的情况下。MQ服务器的消息已经被接收下来并自动给予了ACK回执。有可能造成消息丢失。

        

        二,业务接收代码编写不严谨,没有进行合理的判断。

        

         三,为什么在MQ上的消费者会消失?

               虽然在onMessage里,代码有进行try catch异常。但因为数据问题及程序没有合理判断,同时spring中AspectJ的bug。应该是由于NullException进而引发Error抛出,不能被拦截。所有连接失效。

 

         四,为什么重启,有时候有效有时候无效?

                因为前面提到的编写不严谨,消息一接收就从MQ上进行删除。所有一条错误数据的消息接收一次就消失了,刚好下一条消息是正常的,则重启成功了。如果下一条消息也是错误,不存在的数据,那么tomcat重启后,实际是有建立MQ的消费者的,只是一接收马上又挂了。等我们去console查看时,早已显示无MQ消费者接收了。

 

         五,假设第一条MQ编写严谨,而第二点依然没有进行业务判断,结果如何?

           原系统中,存在一定的将错就错。如果只修改第一条,而第二条不改的话,将造成无限死循环。因为错误结果的消息一直收不到ACK,就直存在于MQ服务器中。

2025-12-01 15:27:47,862 | INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@6e1567f1: startup date [Mon Dec 01 15:27:47 CST 2025]; root of context hierarchy | org.apache.activemq.xbean.XBeanBrokerFactory$1 | main 2025-12-01 15:27:48,126 | ERROR | Failed to load: class path resource [activemq.xml], reason: Line 43 in XML document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 43; columnNumber: 26; cvc-complex-type.2.4.a: 发现了以元素 'whitelistClassFilter' 开头的无效内容。应以 '{"http://activemq.apache.org/schema/core":authorizationPlugin, "http://activemq.apache.org/schema/core":camelRoutesBrokerPlugin, "http://activemq.apache.org/schema/core":connectionDotFilePlugin, "http://activemq.apache.org/schema/core":destinationDotFilePlugin, "http://activemq.apache.org/schema/core":destinationPathSeparatorPlugin, "http://activemq.apache.org/schema/core":destinationsPlugin, "http://activemq.apache.org/schema/core":discardingDLQBrokerPlugin, "http://activemq.apache.org/schema/core":forcePersistencyModeBrokerPlugin, "http://activemq.apache.org/schema/core":jaasAuthenticationPlugin, "http://activemq.apache.org/schema/core":jaasCertificateAuthenticationPlugin, "http://activemq.apache.org/schema/core":jaasDualAuthenticationPlugin, "http://activemq.apache.org/schema/core":loggingBrokerPlugin, "http://activemq.apache.org/schema/core":multicastTraceBrokerPlugin, "http://activemq.apache.org/schema/core":partitionBrokerPlugin, "http://activemq.apache.org/schema/core":redeliveryPlugin, "http://activemq.apache.org/schema/core":runtimeConfigurationPlugin, "http://activemq.apache.org/schema/core":simpleAuthenticationPlugin, "http://activemq.apache.org/schema/core":statisticsBrokerPlugin, "http://activemq.apache.org/schema/core":timeStampingBrokerPlugin, "http://activemq.apache.org/schema/core":traceBrokerPathPlugin, "http://activemq.apache.org/schema/core":udpTraceBrokerPlugin, "http://activemq.apache.org/schema/core":virtualSelectorCacheBrokerPlugin, WC[##other:"http://activemq.apache.org/schema/core"]}' 之一开头。 | org.apache.activemq.xbean.XBeanBrokerFactory | main org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 43 in XML document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 43; columnNumber: 26; cvc-complex-type.2.4.a: 发现了以元素 'whitelistClassFilter' 开头的无效内容。应以 '{"http://activemq.apache.org/schema/core":authorizationPlugin, "http://activemq.apache.org/schema/core":camelRoutesBrokerPlugin, "http://activemq.apache.org/schema/core":connectionDotFilePlugin, "http://activemq.apache.org/schema/core":destinationDotFilePlugin, "http://activemq.apache.org/schema/core":destinationPathSeparatorPlugin, "http://activemq.apache.org/schema/core":destinationsPlugin, "http://activemq.apache.org/schema/core":discardingDLQBrokerPlugin, "http://activemq.apache.org/schema/core":forcePersistencyModeBrokerPlugin, "http://activemq.apache.org/schema/core":jaasAuthenticationPlugin, "http://activemq.apache.org/schema/core":jaasCertificateAuthenticationPlugin, "http://activemq.apache.org/schema/core":jaasDualAuthenticationPlugin, "http://activemq.apache.org/schema/core":loggingBrokerPlugin, "http://activemq.apache.org/schema/core":multicastTraceBrokerPlugin, "http://activemq.apache.org/schema/core":partitionBrokerPlugin, "http://activemq.apache.org/schema/core":redeliveryPlugin, "http://activemq.apache.org/schema/core":runtimeConfigurationPlugin, "http://activemq.apache.org/schema/core":simpleAuthenticationPlugin, "http://activemq.apache.org/schema/core":statisticsBrokerPlugin, "http://activemq.apache.org/schema/core":timeStampingBrokerPlugin, "http://activemq.apache.org/schema/core":traceBrokerPathPlugin, "http://activemq.apache.org/schema/core":udpTraceBrokerPlugin, "http://activemq.apache.org/schema/core":virtualSelectorCacheBrokerPlugin, WC[##other:"http://activemq.apache.org/schema/core"]}' 之一开头。 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399)[spring-beans-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)[spring-beans-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)[spring-beans-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:111)[xbean-spring-4.2.jar:4.2] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:104)[xbean-spring-4.2.jar:4.2] at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)[spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:614)[spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:515)[spring-context-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:64)[xbean-spring-4.2.jar:4.2] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:52)[xbean-spring-4.2.jar:4.2] at org.apache.activemq.xbean.XBeanBrokerFactory$1.<init>(XBeanBrokerFactory.java:104)[activemq-spring-5.15.9.jar:5.15.9] at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:104)[activemq-spring-5.15.9.jar:5.15.9] at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:67)[activemq-spring-5.15.9.jar:5.15.9] at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71)[activemq-broker-5.15.9.jar:5.15.9] at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:54)[activemq-broker-5.15.9.jar:5.15.9] at org.apache.activemq.console.command.StartCommand.runTask(StartCommand.java:87)[activemq-console-5.15.9.jar:5.15.9] at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:63)[activemq-console-5.15.9.jar:5.15.9] at org.apache.activemq.console.command.ShellCommand.runTask(ShellCommand.java:154)[activemq-console-5.15.9.jar:5.15.9] at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:63)[activemq-console-5.15.9.jar:5.15.9] at org.apache.activemq.console.command.ShellCommand.main(ShellCommand.java:104)[activemq-console-5.15.9.jar:5.15.9] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_181] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_181] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_181] at java.lang.reflect.Method.invoke(Method.java:498)[:1.8.0_181] at org.apache.activemq.console.Main.runTaskClass(Main.java:262)[activemq.jar:5.15.9] at org.apache.activemq.console.Main.main(Main.java:115)[activemq.jar:5.15.9]
最新发布
12-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值