使用Jedis连接池报错如何处理?
在使用Jedis连接池JedisPool模式下,比较常见的报错如下:
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
首先确认DCS缓存实例是正常运行中状态,然后按以下步骤进行排查。
- 网络
- 核对IP地址配置
检查jedis客户端配置的ip地址是否与DCS缓存实例配置的子网地址一致,如果从公网访问,则检查是否与DCS缓存实例绑定的弹性ip地址一致,不一致则修改一致后重试。
- 测试网络
- 如果ping不通:
- VPC内访问Redis 3.0或企业版Redis时,要求客户端与DCS缓存实例的VPC相同,安全组相同或者DCS缓存实例的安全组放开了6379端口访问。
- VPC内访问Redis 4.0/5.0/6.0基础版时,要求客户端与DCS缓存实例的VPC相同,Redis实例如果配置了白名单,需确保白名单中包含客户端IP,允许客户端访问,参考配置白名单。
- 公网SSL方式访问Redis 3.0时,要求DCS缓存实例安全组放开了36379端口访问。
- 公网直接访问(非SSL方式)Redis 3.0时,要求DCS缓存实例安全组放开了6379端口访问。
- 如果IP地址可以ping通,telnet对应的端口不通,则尝试重启实例,如重启后仍未恢复,请联系技术支持。
- 如果ping不通:
- 核对IP地址配置
- 检查连接数是否超限
查看已建立的网络连接数是否超过JedisPool配置的上限。如果连接数接近配置的上限值,则建议重启服务观察。如果明显没有接近,排除连接数超限可能。
Unix/Linux系统使用:
netstat -an | grep 6379 | grep ESTABLISHED | wc -l
Windows系统使用:
netstat -an | find "6379" | find "ESTABLISHED" /C
- 检查JedisPool连接池代码
如果连接数接近配置的上限,请分析是业务并发原因,或是没有正确使用JedisPool所致。
对于JedisPool连接池的操作,每次调用jedisPool.getResource()方法之后,需要调用jedisPool.returnResource()或者jedis.close()进行释放,优先使用close()方法。
- 客户端TIME_WAIT是否过多
通过ss -s查看time wait链接是否过多。
如果TIME_WAIT过多,可以调整内核参数(/etc/sysctl.conf):
##当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击 net.ipv4.tcp_syncookies = 1 ##允许将TIME-WAIT sockets重新用于新的TCP连接 net.ipv4.tcp_tw_reuse = 1 ##开启TCP连接中TIME-WAIT sockets的快速回收 net.ipv4.tcp_tw_recycle = 1 ##修改系統默认的TIMEOUT时间 net.ipv4.tcp_fin_timeout = 30
调整后重启生效:/sbin/sysctl -p
- 无法解决问题
如果按照以上原因排查之后还有问题,可以通过抓包并将异常时间点、异常信息以及抓包文件发送给技术支持协助分析。
抓包可使用tcpdump工具,命令如下:
tcpdump -i eth0 tcp and port 6379 -n -nn -s 74 -w dump.pcap
Windows系统下还可以安装Wireshark工具抓包。
公网访问时请将端口改成36379。
网卡名请改成实际的网卡名称。