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