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

相关推荐
indexsunny2 小时前
互联网大厂Java求职面试实战:Spring Boot微服务与Redis缓存场景解析
java·spring boot·redis·缓存·微服务·消息队列·电商
DBA小马哥2 小时前
时序数据库迁移替换与时序数据库分片
数据库·时序数据库
DBA小马哥2 小时前
时序数据库迁移方案在物联网设备监测中的实践与性能突破
数据库·物联网·时序数据库
ID_180079054732 小时前
小红书笔记详情API接口基础解析:数据结构与调用方式
数据结构·数据库·笔记
无心水2 小时前
【分布式利器:腾讯TSF】7、TSF高级部署策略全解析:蓝绿/灰度发布落地+Jenkins CI/CD集成(Java微服务实战)
java·人工智能·分布式·ci/cd·微服务·jenkins·腾讯tsf
28岁青春痘老男孩7 小时前
JDK8+SpringBoot2.x 升级 JDK 17 + Spring Boot 3.x
java·spring boot
方璧7 小时前
限流的算法
java·开发语言
元Y亨H7 小时前
Nacos - 服务注册
java·微服务
曲莫终8 小时前
Java VarHandle全面详解:从入门到精通
java·开发语言
ruleslol8 小时前
MySQL的段、区、页、行 详解
数据库·mysql