两次连接池泄露的BUG

问题1

现象

1、WEB服务发版不报错,但运行一段时间后,服务假死,请求卡住,需要重启才能解决;

排查过程

1、重启,恢复正常,但过几个小时又复现,确定不是偶现BUG; 2、在再次复现的时候,打印线程日志,是否线程耗尽;

bash 复制代码
jstack <pid> > /tmp/thread.log

3、让运维重启,先让服务正常,开发同步分析BUG产生原因;

4、排查发现,新增代码有很多WAITING,等待线程连接,猜测是否是线程池未回收,导致WEB线程一直卡住,后面WEB线程池耗尽的问题;

5、排查代码,使用了JedisConnectionFactory对象获取连接,为了使用eval,需要jedis对象,这种获取对象的方式,需要手动归还连接,close(还回连接池);

6、更新代码,重新发版,bug不在出现,问题解决;

问题2

现象

1、服务发版,多个节点都正常,但突然有一个节点出现了Redis连接变成了9500多报警,还一直不能降下去;

排查过程

1、排查是否真的有这么多连接,是否是监控误报,登录Redis,查看connected_clients数量,确实是9500多;

bash 复制代码
 INFO clients

2、查看连接详情,发现大绝大部分连接是SELECT(切换redis数据库),PING(心跳维持Redis连接,心跳维持连接,就表示创建的连接不会自动关闭,因为做了心跳维持),并且age和idle时间很近,说明连接都是活跃的连接,不是没有用的连接,心跳PING其实也会让连接保持活跃;

bash 复制代码
CLIENT LIST

3、排查为什么会有建立这么多连接,是有代码用了for循环在创建连接吗,不太可能有人这样做,人为无缘无故创建这么多连接,不正常;

4、排查代码,主要是这次发版的几个服务,发现有两种方式创建redis连接池,一种是Spring

Cloud的,默认最大200个,idle最大最小是50个,并且用法就是redisTemplate,这个基本不可能有这种泄露的问题,毕竟是一个这么成熟的开源工具,除非像上面一样用JedisConnectionFactory获取对象,但又不关闭,里面又用了定时任务做redis操作,但这次发版没有修改redis,所以概率太低;

5、再一种情况就是自定义连接池,这也是重点怀疑目标,这个连接池用的最大连接是150,应该也算不到这么大,排查发现写的自定义连接池,是懒加载方式,在使用的时候通过单例调用,但这个连接池是创建之后放入map中,初看没有啥问题,但细看就会发现,如果同时多个获取连接打到了初始化的地方,并且都进入了 inst=null的位置,而初始化过程又是一个比较长的过程,那不就出BUG了;

6、这个连接被网关服务使用,网关服务重启,会有批量设备重连,重新登录需要鉴权,redis,所以会导致创建多个redis连接池,但map覆盖后,实际使用的连接池只有最后一个,但因为连接池设置为维持连接模式,也就是会PING,导致那些覆盖的连接也不会回收,从而触发连接数量暴增问题;

7、调整代码,加锁,重新发版,连接就不会变的这么大,问题解决;

相关推荐
身如柳絮随风扬4 小时前
Java中的CAS机制详解
java·开发语言
qq_192779875 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python
风筝在晴天搁浅5 小时前
hot100 78.子集
java·算法
u0109272716 小时前
使用Plotly创建交互式图表
jvm·数据库·python
爱学习的阿磊6 小时前
Python GUI开发:Tkinter入门教程
jvm·数据库·python
故事和你916 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
tudficdew6 小时前
实战:用Python分析某电商销售数据
jvm·数据库·python
sjjhd6527 小时前
Python日志记录(Logging)最佳实践
jvm·数据库·python
Configure-Handler7 小时前
buildroot System configuration
java·服务器·数据库
2301_821369617 小时前
用Python生成艺术:分形与算法绘图
jvm·数据库·python