首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spring编程式事务处理不当引起的连接泄露事件

某一日正在孜孜不倦的研究代码,忽然测试童鞋说系统服务挂了,完全不可用。

程序大量抛出如下异常:

对于程序员来说,系统宕机就是军令,更可况是难得一见的连接池泄露问题。因为在企业级的Java项目中,一般采用连接池技术和Spring的事务管理技术来处理数据访问需求,而这两项技术都是久经考验的成熟可靠技术,出问题的几率很小。

其实从异常堆栈来看,明确指出连接池中的连接全部处于激活使用的状态

按照我个人经验来说,连接耗尽可能有两种原因:

1. 系统负载很高,总连接数确实不够用,因此资源耗尽。

2. 数据库连接出现泄漏,无法正常回收,资源只出不进,导致资源耗尽。

第一种可能性很好验证,调整连接池配置参数`maxActive=500`,观察系统是否健康运行。但调整之后验证失败,500个连接依然迅速耗尽,那基本上确认是连接泄露问题。

首先要定位可能导致连接泄露的代码位置,查看系统运行日志,果然从中找出蛛丝马迹(注:资源使用的异常处理机制非常重要不可或缺,否则大海捞针全靠猜)。

日志中发现ERROR信息:

这个ERROR连续出现N次之后,系统抛出CannotGetJdbcConnectionException,猜测很有可能问题就出现在这里。

`No value for key`的告警信息初始体现在Spring框架TransactionSynchronizationManager的unbindResource方法中,源码如下:

从源码中可以看出,Spring在线程中unbind resource时,发现待处理的key不存在,抛出异常,终止了资源释放处理过程。

Spring的资源释放流程简图如下:

了解了这个过程之后,仔细分析异常日志中的代码行数,发现其中有一行编程式的事务处理代码:

具体为什么写这一行,在这里就不再赘述了。但是因为这个编程式的事务处理逻辑不当,错误的unbind dataSource,导致后续Spring的资源处理过程中(上图第2步)处理失败,无法继续回收数据库连接,连接只能获取不能回收,因此资源池迅速耗尽。

问题基本上已经明确解决,但因此衍生的思考是Spring的事务处理机制原理。

每一次线上问题的处理,都需要深刻理解背后的技术原理,多体验多分析多积累!

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171229G11SJC00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券