开发者社区 问答 正文

使用 Jedis 连接池模式容易遇到无法获取连接池的错误有哪些

使用 Jedis 连接池模式容易遇到无法获取连接池的错误如下所示。 redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

可以根据以以下几种原因进行分类排查。
网络检查
首先检查是否网络问题,可以通过 telnet host 6379进行简单测试,连上之后 auth 密码回车查看是否返回 +OK\r\n,如果能够正确返回继续检查 ping请求或者读写请求是否正常返回,操作多次排查网络问题影响。
JedisPool 连接数设置检查
JedisPool 使用的时候需要进行连接池的设置,用户在超过 MaxTotal 连接数的时候也会出现获取不到连接池的情况,这个时候可以在访问客户端上通过 netstat -an | grep 6379 | grep EST | wc -l查看链接的客户端链接数目,并且比较这个数目和 JedisPool 配置的 MaxTotal 的值,如果没有明显超过或者接近就可以排除 JedisPool 连接池配置的影响。
JedisPool 连接池代码检查
对于 JedisPool 连接池的操作,每次 getResource 之后需要调用 returnResource 或者 close 进行归还,可以查看代码是否是正确使用,代码示例如下: JedisPoolConfig config = new JedisPoolConfig();
//最大空闲连接数, 应用自己评估,不要超过ApsaraDB for Redis每个实例最大的连接数
config.setMaxIdle(200);
//最大连接数, 应用自己评估,不要超过ApsaraDB for Redis每个实例最大的连接数
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
String host = "*.aliyuncs.com";
String password = "密码";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
try {
    jedis = pool.getResource();
    /// ... do stuff here ... for example
    jedis.set("foo", "bar");
    String foobar = jedis.get("foo");
    jedis.zadd("sose", 0, "car");
    jedis.zadd("sose", 0, "bike");
    Set<String> sose = jedis.zrange("sose", 0, -1);
} finally {
    if (jedis != null) {
        jedis.close();
    }
}
/// ... when closing your application:
pool.destroy();


检查是否发生 nf_conntrack 丢包
通过 dmesg 检查客户端是否有异常。 nf_conntrack: table full, dropping packet

如果发生 nf_conntract 丢包可以修改设置 sysctl -w net.netfilter.nf_conntrack_max=120000
检查是否 TIME_WAIT 问题
通过 ss -s查看 time wait 链接是否过多。

如果 TIME_WAIT 过多可以修改以下参数: sysctl -w net.ipv4.tcp_max_tw_buckets=180000
sysctl -w net.ipv4.tcp_tw_recycle=1


检查是否 DNS 解析问题
通过在 /etc/hosts 文件直接绑定 host 地址,绑定完成之后查看问题是否还存在,如果还存在则不是 DNS 解析问题。 192.168.1.1  *.redis.rds.aliyuncs.com


需要帮助


如果按照上面排查之后还有问题可以通过抓包并将报错时间点、报错信息、抓包文件发送给阿里云售后同学进行分析。抓包命令为 sudo tcpdump -i eth0 tcp and port 6379 -n -nn -s 74 -w redis.cap

展开
收起
云栖大讲堂 2017-10-30 13:53:54 2515 分享 版权
阿里云 AI 助理回答

面对您描述的问题,您已经进行了非常详细的排查步骤,涵盖了网络连接、JedisPool配置、资源管理、系统设置以及DNS解析等多个方面。如果经过上述所有步骤的检查和调整后问题仍然存在,这可能意味着问题根源在于更深层次的配置错误、系统限制或是服务端问题。以下是一些建议的后续步骤:

  1. 日志分析:查看Redis服务器端的日志,了解在客户端尝试连接失败时,服务器是否有相关错误或警告信息输出。这有助于识别是否是服务器配置不当、达到最大连接数限制、或者是Redis服务本身的问题。

  2. 阿里云控制台检查:登录阿里云Redis实例的管理控制台,检查实例的状态、性能指标(如CPU使用率、内存使用情况)、连接数统计等,确认实例是否运行正常且未达到其资源上限。

  3. 防火墙与安全组设置:确认实例所在的安全组规则是否允许您的应用服务器IP访问Redis服务的6379端口。有时候,即使telnet测试通过,安全组策略的变更也可能影响到实际应用的连接。

  4. 版本兼容性:检查您使用的Jedis客户端版本与阿里云Redis服务的版本是否兼容。不兼容的客户端可能会遇到一些已知问题。

  5. 超时设置:检查Jedis客户端的超时设置(如连接超时、读写超时),确保这些值设置得合理,既不过短导致频繁超时,也不宜过长导致资源占用。

  6. 监控与报警:考虑在应用中集成阿里云提供的监控工具,对Redis连接池的使用情况进行实时监控,并设置适当的报警阈值,以便于及时发现并处理潜在问题。

如果以上建议仍不能解决问题,确实应该考虑收集更详细的信息,包括但不限于: - 报错的具体时间点。 - 完整的报错堆栈信息。 - 通过tcpdump抓取的网络包文件,特别是报错发生时段的网络通信记录。 - Redis服务端及客户端的配置详情。 - 应用程序的日志,尤其是与Redis操作相关的部分。

然后,将这些信息整理好后联系阿里云的技术支持团队,他们能够基于这些具体数据进行深入分析,提供针对性的帮助。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答