场景描述:
临下班时,突然接到电话。说某个客户的生产环境上,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服务器中。
相关推荐
apache-activemq-5.16.0.zip
spring.activemq.broker-url=failover:(tcp://10.0.1.227:61616,tcp://10.0.1.228:61616,tcp://10.0.1.229:61616,mqtt://10.0.1.227:1883,mqtt://10.0.1.228:1883,mqtt://10.0.1.229:1883) #spring.activemq.broker-...
apache-activemq-5.15.15二进制包,安装包,apache-activemq-5.15.15-bin.tar.gz
1.解压 ...ACTIVEMQ_HOME=/opt/apache-activemq-5.15.12 PATH=/opt/apache-activemq-5.15.12/bin:$PATH export ACTIVEMQ_HOME PATH 5.activemq的后台默认端口是61616,前台访问端口是8161
Apache ActiveMQ是Apache软件基金会的一个开源项目,是一个基于消息的通信中间件。ActiveMQ是JMS的一个具体实现,支持JMS的两种消息模型。ActiveMQ使用AMQP协议集成多平台应用,使用STOMP协议通过websockets在Web...
apache-activemq-5.16.6-bin.zip
apache-activemq,运行需要依赖的jdk版本为11+
activemq-all.5.14jar包,亲测可用!!
activemq-5.15.15 JDBC持久化mysql8.0+的activemq.xml
apache-activemq-5.15.11-bin.rar是ActiveMQ,用于做消息队列,里面包含windows和linux两个版本。
apache-activemq-5.8.0.zip 能直接使用的官方原版 apache-activemq-5.8.0.zip 能直接使用的官方原版
ActiveMQ 5.15.11 Linux版,
基于JMS消息中间件activemq5.13.5版本,apache-activemq-5.13.5-bin.zip
apache-activemq-5.16.5,启动要求jdk版本8+
工具包~~~~·Java apache-activemq-5.12.0.zip的压缩包
ActiveMQ是一种开源的基于JMS(Java Message Servie)规范的一种消息中间件的实现
activemq, Apache ActiveMQ镜像 欢迎来到 Apache ActiveMQis是一个高性能的Apache 2.0许可以消息代理和 JMS 1.1实现。正在启动要帮助你入门,请尝试以下链接:入门http://activemq.apache.org/version-
官方版本,亲测可用
开发activemq发送程序,遇到问题 (1)Qt5AxContainer.lib error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“1” Qt5AxBase.lib error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的...