Dubbo 线程污染 DruidDataSource getConnection 报中断异常 interrupt

博文目录


JDK Thread interrupt 中断

问题说明

Spring dubbo 服务, 偶尔会报如下异常

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: interrupt
...

近期有修改过接口最外层 try-catch, 在 catch 块里添加了 Thread.currentThread.interrupt();

这是一个不当的修改

导致当有请求发生异常时, 线程会被设置中断标记, 然后线程被归还回 Dubbo 线程池, 当之后的某个请求使用了该线程, 执行到 DruidDataSource.getConnectInternal() 方法时, 会加一个可以响应中断的锁, 当有中断异常时, 会抛一个 SQLException(“interrupt”, e), 该方法内部调用到了 AQS.acquireInterruptibly, 里面会先判断当前线程是否被设置了中断标记, 如果有则直接抛出中断异常, 所以最终就抛出了 SQLException, 且 message 为 interrupt

# DruidDataSource.getConnectInternal()
try {
	lock.lockInterruptibly();
} catch (InterruptedException e) {
	connectErrorCount.incrementAndGet();
	throw new SQLException("interrupt", e);
}
# java.util.concurrent.locks.ReentrantLock#lockInterruptibly
public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}
# java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireInterruptibly
public final void acquireInterruptibly(int arg)
         throws InterruptedException {
     if (Thread.interrupted())
         throw new InterruptedException();
     if (!tryAcquire(arg))
         doAcquireInterruptibly(arg);
 }

问题解决

删除不当位置的 Thread.currentThread.interrupt();

建议, 除非你真的知道为什么需要 Thread.currentThread.interrupt();, 否则不要瞎用

要用也是在 InterruptedException 的 catch 中用, 不要在 Throwable / Exception 级别的 catch 中用

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值