线上碰到一个问题:
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

at redis.clients.util.Pool.getResource(Pool.java:22)

线上会相隔不定时的天数后出现一次JedisPool种getresouce拿不到resource的情况。中间陆陆续续上过很多次线,然后废了很大劲努力排除掉了业务可能和多次上线的代码问题。业务数据量即便是在测试环境种建造了更多,也不会导致那种情况的出现。而业务代码测试环境和线上相同,后来在测试环境压测的压力和线上差不多的情况下,也不会重现这个问题。
后来就有一种束手无策的感觉了,最后只能推论是当时应用集群到Redis集群的网络出了问题了,但是由于种种原因一直没有在集群间添加网络状态的监控,也就只能是猜测了,但是又没办法重现。后来偷偷在线上的一台服务器上面添加了ping的监控,很简单:ping -i 1 192.168.134.155 > pinglog_{`date +%Y-%m-%d`}.log &,该命令的效果比较简单,就是每隔1sping一次目标服务器,然后打印到按天分开的日志里面。然而这种事情不再出现我们酒没办法验证推论,领导又催的非常紧,没办法还是需要验证出来啊。
开始的时候,根据代码来找原因,代码里面从jedispool种获得jedis资源实例的代码是使用了java7里面的try-with-resouce的写法,也就是用完之后,于是就怀疑是不是这种写法,在try块里面有了其他异常会导致resouce无法正常关闭,导致某个Jedis实例用完后没有还给JedisPool,导致资源不足?

public class JedisTest {private static final JedisPool jedisPool;static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxIdle(20);config.setMaxTotal(40);config.setMinIdle(10);jedisPool = new JedisPool(config, "127.0.0.1", 8279, 1000);}public static void main(String[] args) {try(Jedis jedis = jedisPool.getResource()){throw new Exception("~");}catch (Exception e){//do nothing
        }}
}

后来其实在JedisPool里面的断点很容易就可以看到java7 并没有错误,多心了。

于是,那还是回归主题,其实只要认真分析,不会又那么困难的问题出现:
其实getresouce报错有两种可能:
1、本身有错误---排除,首先如果这个方法有错误,那么之前应该会一直出现,或者其他人也早该把开源包的错误爆出,排除这种可能;
2、就是在规定时间内没取到资源。
刚才我们看maxtotal里面定义了池子最大就40个,如果真的40个都在用,并且在超时的100ms内没人return resouce,那报错也正常。
也就是说,我们出现了40个全部被用到,并且在超时的100ms内没有任何资源还给JedisPool。
后来恰好,在打印的jstack的信息种发现了大量的time_waiting状态的线程在等待从Jedispool.getResouce().
那么什么情况下会导致这个情况出现?
假设现在并发来了41个请求,然后其中40个正常的进行,但是第41没拿到资源,于是等待规定的超时时间,但是这会从应用到Redis集群间网络出现抖动,暂时不通,会导致40个请求种的里面的jedis的get或者set操作变慢甚至超时。
我们设想一种情况:从jedisPool里面拿资源的超时时间是100ms,程序里面进行get或者set资源的是200ms超时,那么就有可能出现这种情况。
事实证明我们的配置确实是jedis里面去get或者set一个key的时候,超时时间是200ms,那也就是说,如果网络发生了抖动,那就会在并发的情况下迅速耗光资源池,然后超时后报错才还回去,但是那个时间早就发生了getResouce的错误。
Bingo,其实很简单的原因,那就是没有正确的理解两个超时时间之间的关系。
我们可以简单测试一下:

public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(20);for(int i = 0;i < 20 ;i ++){service.execute(new Runnable() {@Overridepublic void run() {try(Jedis jedis = jedisPool.getResource()) {Thread.sleep(200L);} catch (InterruptedException e) {System.out.println(e);}}});}}

由于本地环境问题,只是示例代码,就不执行了。其实很容易就还原了问题出来。

后面只要调小jedis的get和set方法的超时时间,同时也尽量小的使用getresource的超时时间(这里为什么不加大,因为在高并发的情况下会迅速耗光线程数量,jstack里面甚至出现了500个线程有450个是time_waiting的状态,这可不是我们想要的结果)。

然后在服务器之间添加监控和警报,及时报警进行网络的修复。

转载于:https://www.cnblogs.com/congsg2016/p/5328976.html

JedisPool无法获得资源问题相关推荐

  1. JedisPool资源池优化

    本文作者:carlosfu 原文链接:https://yq.aliyun.com/articles/236383 摘要: 合理的JedisPool资源池参数设置能为业务使用Redis保驾护航,本文将对 ...

  2. Hrm-人力资源系统开发笔记05

    1.无限极树优化 1.1.为什么要优化 每次都要从数据库查询一次. 使用的地方&问题: 1)后台管理 课程类型列表要使用 课程类型树,在后面添加课程时会反复使用.通过下拉选择对应的类型 就算每 ...

  3. webapi控制器怎么接收json_一个秒杀系统的登录系统到底是怎么工作的

    本部分内容 这部分主要是从客户端输入网址到登录成功 进入主页 一般来说,输入的网址会被controller层拦截,但是如果在只输入了主机,没有输入其他的内容那么就会默认载入template中的inde ...

  4. 搭建一个完整的微服务项目

    一.项目技术架构 1.技术栈 前台技术 Node.js.Npm.Vue.js.WebPack.Vue Cli.Element UI 后台架构 微服务架构:按照功能拆分N多个服务,每个服务可以独立技术选 ...

  5. 基于Redis实现简单的分布式锁

    在分布式场景下,有很多种情况都需要实现最终一致性.在设计远程上下文的领域事件的时候,为了保证最终一致性,在通过领域事件进行通讯的方式中,可以共享存储(领域模型和消息的持久化数据源),或者做全局XA事务 ...

  6. Java异常 | JedisException: Could not get a resource from the pool

    1. 异常现象 20190429 16:27:58,200 | ERROR | (RedisClient.java:262)RedisClient:262 - jedisInfo ... NumAct ...

  7. HRM人力资源系统-Day05

    课程类型的优化 无限极树的优化 方案一:发送一条SQL 将所以数据都查询出来 然后在通过循环将子级节点放入到父级节点中 代码实现: //循环方案-一条sql自己组织关系 private List< ...

  8. hrm项目-day02

    文章目录 一.课程分类树状展示 1.前端(略过不用管) 2.后台课程服务编写查询方法 1.CourseTypeController编写查询方法 2.CourseTypeService实现方法 3.实现 ...

  9. Springcloud HRM微服务项目(二)

    文章目录 课程类型数据查询 1.如何查询数据 2.如何封装数据 3.配置跨域 给课程分类做缓存 1.简介 2.搭建基础服务 3.集成redis 1.导包 2.工具类 3.测试工具类 4. redis服 ...

最新文章

  1. 数据科学中的6个基本算法,掌握它们要学习哪些知识
  2. windows下快速启动或关闭系统服务方法
  3. 深入async/await知多少
  4. axios安装_一起学Vue:访问API(axios)
  5. 高职计算机等级考试试题,高职院校计算机等级考试的教学与思考
  6. visual studio Code配置C++环境:
  7. 一个奇怪的问题:tomcat 栈溢出 StackOverflowError错误
  8. EJB3.0框架实例----区分有状态bean和无状态bean
  9. 安装mysql第三步卡死_Mysql 安装服务无法启动解决方案与使用的一般使用指令
  10. 使用Spring Data JPA作为持久层框架
  11. iocomp iPlot使用说明13 Limits绘图界限
  12. 公众号900篇文章分类和索引
  13. Android 关于图片的压缩
  14. js写的 几款时间轴
  15. 冰峰王座完整的语音英文+中文解释!(修订版)
  16. Lua 报错 PANIC: unprotected error in call to Lua API (no calling environment) 解决办法
  17. MAC打印出现Filter failed
  18. 10005 内联函数
  19. Linux_进程控制(创建进程,等待进程,进程终止)
  20. javaee.jar与servlet-api.jar

热门文章

  1. python 多进程中锁的使用方法
  2. window上远程访问linux上的neo4j的设置
  3. 禁止vim生成 un~文件
  4. xgboost算法 c语言,xgboost与sklearn的接口
  5. python3如何使用mysql_python3怎么用sqlalchemy操作mysql
  6. linux登出系统,讲解Linux操作系统进入与退出系统方法
  7. 笔记-知识产权与标准化知识-计算机软件可靠性和可维护性管理的评审要求
  8. PHP基础知识(二)
  9. Node中同步与异步的方式读取文件
  10. gRPC的通信方式-客户端流式、服务端流式、双向流式在Java的调用示例