问题:
我们线上有个服务叫做LightParser,做一些Query改写等工作。在线上跑了很久没有问题,突然收到一个报警,说超时,延迟200ms,它平常只要20ms左右,马上上机器去看问题。发现连接池满了,jedis不能从连接池获取连接。再netstat一下,发现连接redis的连接远远没有连接池里这么多。连接池设置了200个,实际连接只有5~6个。
分析:
一开始是怀疑连接没有归还,把以前使用的returnBroke什么的归还方式换成了连接close。但是没有效果。然后才认为是redis server关闭了连接,客户端没有感知到。
解决:
JedisPoolConfig config = new JedisPoolConfig(); config.setTestOnBorrow(true);
首先打开testOnBorrow选项,该选项开启,jedis会在从连接池拿连接的时候ping一下,验证该连接是否可用,可用就取出来,不可用就丢弃。
但是打开这个选项的时候报了一个异常:
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
看了源代码后原来是密码的问题,由于拿到连接的时候就要ping一下,而redis没有密码是不能ping的,所以会抛这个异常。
只要在建立连接池的时候加上密码即可。
JedisSentinelPool jedisPool = new JedisSentinelPool("master", sentinels, config, "password");
上线后,查看debug日志,果然没有连接池中的连接持续增长的问题了。