文档章节

ActiveMQ:No operations allowed after statement ...

旁观者-郑昀
 旁观者-郑昀
发布于 2012/11/10 00:21
字数 1063
阅读 180
收藏 1
ActiveMQ版本:5.5.1
记录人:@郑昀
现象:
系统现象:部分消息发送失败,失败频率不正常。
日志信息:activemq.log 中一直有这样的错误日志:

JDBC FailureNo operations allowed after statement closed.

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.

        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

…………


        at org.apache.activemq.transport.InactivityMonitor.onCommand(InactivityMonitor.java:227)

        at org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)

        at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:220)

        at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:202)

        at java.lang.Thread.run(Thread.java:662)

Close failed: Already closed.

看上去又是 mq broker 失去了数据库连接,但代码仍尝试在此连接上执行操作,所以 jdbc 直接抛异常。

原因:
ActiveMQ 持久化方案我们选的是 MySQL 。
如果 mq 与 db 之间的数据库连接,因为 数小时的不活动(inactivity),那么 MySQL 就会根据自身的 wait_timeout 参数设置 主动断开连接。这一点在之前的“ ActiveMQ:Communications link failure问题以及解决办法”文章中讲过。
只不过,遇到此问题时,
mq client 端报告“com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure”错误,
而 mq server 端则报告“ com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed. ”错误。
即原因是,mq broker service 试图在已关闭的数据库连接上继续执行操作
缺陷单 AMQ-2534 甚至报告“

Broker gets stuck with an error about using a closed JDBC statement

”,我们很难说此时 mq broker service 会不会真的“卡住”。

解决办法:
“ActiveMQ:Communications link failure问题以及解决办法”文章讲的一样,
最简单办法,还是根据业务特点,调整 ActiveMQ 所使用的 MySQL 的全局变量 wait_timeout 值,
尽量减少数据库连接因为 inactivity 而被关闭的几率 

或者在 mq client 里主动捕获 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException 异常,手动重新连接即可:
  1.         } catch (SQLException sqlEx) {  
  2.             String sqlState = sqlEx.getSQLState();  
  3.            // 08S01就是这个异常的sql状态。单独处理手动重新连接即可。  
  4.             if ("08S01".equals(sqlState) || "40001".equals(sqlState))   

为什么 Connector/J 不自动重连而非要抛出异常:
下面的文字翻译自 MySQL 5.5  Connect/J 疑难问题文档
23.3.15.13: 为什么遇到  communication failure 之后,  Connector/J 不能自己重新连上数据库,然后重新提交事务呢,而是非要抛出一个异常,即使我用了 autoReconnect 连接字符串属性?
答:有几个原因。
第一个,保证事务完整性。MySQL 的帮助文档上曾说过:“ there is no safe method of reconnecting to the MySQL server without risking some corruption of the connection state or database state information ”。
可以看一下这个案例:
01.conn.createStatement().execute(
  "UPDATE checking_account SET balance = balance - 1000.00 WHERE customer='Smith'");
02.conn.createStatement().execute(
  "UPDATE savings_account SET balance = balance + 1000.00 WHERE customer='Smith'");
03.conn.commit();
考虑一下这个场景:执行完01后,数据库连接断了。
如果没有异常抛出的话,应用程序永远不知道这个问题,仍继续执行。
但是第一个事务并没有提交,所以它回滚了。
如果没抛异常,数据库连接自动重连,于是第二个事务被提交了。
从而破坏了事务完整性(transactional integrity)

记住,此时 auto-commit 于事无补。当 Connector/J 遇到 communication problem ,你不知道服务器端是否处理了这个事务,有几种可能:
  • 服务器端没有接到这个事务,因此什么也没发生;
  • 服务器端接到了且执行了,但客户端没有收到 Response 。

第二个原因是,事务里上下文相关数据有可能非常脆弱 ,如:
  • 临时表;
  • 用户自定义变量;
  • 服务器端预处理语句(Server-side prepared statements);
如果数据库连接断开了,很可能这些数据也消失了;如果此时不抛出异常而是自动重连,你的应用程序很可能跑飞了。

总结:
1)silently reconnecting”可能非常不安全,将衍生出很多不可控问题。所以最佳策略是,通知应用程序到底发生了什么,然后由应用开发者决定如何处理
2)mq的生产者频繁报“com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure”和mq server自己频繁报“com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed”,都是因为 mysql  wait_timeout 导致数据库连接因为不活动而被主动关闭。


参考资料:


© 著作权归作者所有

旁观者-郑昀
粉丝 100
博文 77
码字总数 162700
作品 0
朝阳
私信 提问
Zabbix监控ActiveMQ

当我们在线上使用了ActiveMQ 后,我们需要对一些参数进行监控,比如 消息是否有阻塞,哪个消息队列阻塞了,总的消息数是多少等等。下面我们就通过 Zabbix 结合 Python 脚本来实现对 ActiveMQ...

SEOwhywhy
06/26
24
0
.Net平台下ActiveMQ入门实例

1.ActiveMQ简介 先分析这么一个场景:当我们在网站上购物时,必须经过,下订单、发票创建、付款处理、订单履行、航运等。但是,当用户下单后,立即跳转到“感谢那您的订单” 页面。不仅如此,...

postdep
2015/08/24
90
0
activemq服务无法正常启动

2012-09-26 13:26:41,092 | INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@1a7e798: startup date [Wed Sep 26 13:26:41 CST 2012]; root of context hierarchy | org.......

子萧
2012/09/26
551
0
Activemq java.net.BindException: Address already.

错误堆栈信息如下: 2014-04-24 13:53:22,911 | INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@3ef810: startup date [Thu Apr 24 13:53:22 CST 2014]; root of context......

ITFrank
2014/04/24
2.7K
1
CentOS设置开机自动启动服务

以activemq为例 1. 安装ActiveMQ到/opt/apache-activemq/ 2. 创建软连接到init.d目录: sudo ln -s /opt/apache-activemq/bin/activemq /etc/rc.d/init.d/activemq 这个时候,就可以用servi......

Jarhf
05/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kafka实战(五) - 核心API及适用场景全面解析

1 四个核心API ● Producer API 允许一个应用程序发布一串流式的数据到一个或者多个Kafka topic。 ● Consumer API 允许一个应用程序订阅一个或多个topic ,并且对发布给他们的流式数据进行处...

JavaEdge
今天
11
0
实现线程的第三种方式——Callable & Future

Callable Runnable 封装一个异步运行的任务, 可以把它想象成为一个没有参数和返回值的异步方 法。Callable 与 Runnable 类似, 但是有返回值。Callable 接口是一个参数化的类型, 只有一 个...

ytuan996
今天
12
0
OSChina 周六乱弹 —— 不要摁F了!

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 : 朴树写的词曲都给人一种莫名的失落感,不过这首歌他自己却没有唱,换成赵传这种高音阶嘶喊的确很好,低沉但却有力,老男人的呐喊...

小小编辑
今天
22
0
Android Binder机制 - interface_cast和asBinder讲解

研究Android底层代码时,尤其是Binder跨进程通信时,经常会发现interface_cast和asBinder,很容易被这两个函数绕晕,下面来讲解一下: interface_cast 下面根据下述ICameraClient例子进行分析...

天王盖地虎626
昨天
13
0
计算机实现原理专题--存储器的实现(二)

计算机实现原理专题--存储器的实现(一)中描述了一种可以记住输入端变化的装置。现需要对其功能进行扩充,我们将上面的开关定义为置位,下面的开关定义为复位,然后需要增加一个保持位,当保...

FAT_mt
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部