两次连接池泄露的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、调整代码,加锁,重新发版,连接就不会变的这么大,问题解决;

相关推荐
独泪了无痕1 小时前
探索Pinyin4j-Java中的拼音转换利器
java·后端
道尔柯南2 小时前
C++ string 类详解:从常用接口到深拷贝,彻底掌握字符串处理
android·java·c++
Nturmoils3 小时前
集中式与分布式怎么选:从订单读写看 KingbaseES 的架构边界
数据库
xiaomuzuirenzhen3 小时前
大专电子商务从事电商运营分析师需要考证吗?
大数据·数据库
kingx33 小时前
Bugku 3122 谷歌小恐龙题解:纯离线逆向 Vault 的 AES-GCM 加密资源(附 Python 解密器)
java·逆向·ctf·bugku·aes-gcm
翔云1234565 小时前
RocksDB中,客户端每写入一次数据,需要访问几次磁盘
运维·数据库·mysql
DevOpenClub5 小时前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
露天赏雪6 小时前
第3篇:Sentinel熔断降级实战:大模型接口抖动时的服务兜底方案
java·开发语言·人工智能·spring boot·spring·servlet·sentinel
天天被压力6 小时前
【A股分钟级高频数据完全手册 #06】北交所分钟级数据接口:京市股票Pro版最新分时
java·人工智能·python
GeW6 小时前
新质生产力路线图解读:数据库性能优化与Linux调优专场
linux·数据库