0
点赞
收藏
分享

微信扫一扫

JedisPool异常:Could not get a resource from the pool

JedisConnectionException: Could not get a resource from the pool  -------无法从连接池中获取到连接(资源)。

具体原因主要看异常堆栈信息里的Caused By子句。

 

下面Caused by可知,在调用borrowObject获取idle连接时,由于池中没有idle连接,出现阻塞等待,结果发生等待超时。

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)

 

下面Caused by可知,同样在从池中获取idle连接时,由于池中没有idle连接,并且设置了不等待(blockWhenExhausted=false),故出现异常。

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

Caused by: java.util.NoSuchElementException: Pool exhausted
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

 

而我们的优付trans今天出现了如下Caused by的异常--- Pool not open。

2022-12-12 10:09:10.080 WARN  [clientBusiness_common_1670810950078S930,TID:d09088df43334542893d6ffc06399ff6.132.16708109500416701,0308d204b0a94d8eb6dd1b48ae72bcec] com.yft.opencommon.cache.JedisUtils:854 :getResource.
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.java:53)
at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
at com.yft.opencommon.cache.JedisUtils.getResource(JedisUtils.java:851)
at com.yft.opencommon.cache.JedisUtils.get(JedisUtils.java:53)
at com.cn.yft.cache.RedisCacheUtil.getMerReqLimit(RedisCacheUtil.java:213)

Caused by: java.lang.IllegalStateException: Pool not open
at org.apache.commons.pool2.impl.BaseGenericObjectPool.assertOpen(BaseGenericObjectPool.java:759)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:395)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:346)
at redis.clients.util.Pool.getResource(Pool.java:49)
... 76 common frames omitted

持续时间从上午10:09:10.080~10:17:00.306,影响部分客户下发。运营反馈后,立即重启服务暂时得到解决。

排查:

优付trans有4个节点做负载:两台在IDC机房、两台在联通云机房,双机房有专线。redis是单节点,服务器在IDC机房。当时只有联通云机房5号节点出现这个异常,其他节点未发现。 当然,这与各节点QPS以及redis操作数量有关,并不一定都会出现这个异常。

抛出Pool not open异常的源码在commons-pool2的BaseGenericObjectPool里

/**
* Verifies that the pool is open.
* @throws IllegalStateException if the pool is closed.
*/
final void assertOpen() throws IllegalStateException {
if (isClosed()) {
throw new IllegalStateException("Pool not open");
}
}

而后发现程序里JedisPool的配置,maxIdle配置的是1。

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="1" /> <!-- 资源池允许最大空闲的连接数 -->
<property name="maxTotal" value="300" /> <!-- 资源池中最大连接数 -->
<property name="testOnBorrow" value="true" /> <!-- 当调用borrowObject方法时,是否进行有效性检查 -->
</bean>

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig"/>
<constructor-arg index="1" value="${redis_ip}" type="java.lang.String"/>
<constructor-arg index="2" value="${redis_port}" type="int"/>
<constructor-arg index="3" value="${redis_expire}" type="int"/>
<constructor-arg index="4" value="${redis_password}" type="java.lang.String"/>
</bean>

分析最大原因应该是当时系统需要操作redis的逻辑太多,而jedis配置不合理,导致了这个异常的出现。一个同学在本地测试环境通过并行测试,也有模拟出来这个异常。

当天晚上,将maxIdle改为200上线,经过持续一天的观察未见异常。

 

关于Pool not open异常,网上这篇技术贴写的不错。​​JedisPool 在关闭情况下为什么 还能提供连接资源 并且 只有一个线程一直拿不到连接资源​​

 

 

微信公众号里也发现一篇文章,​​https://mp.weixin.qq.com/s/EWH-buDjBthxH6UGrFdP1w​​ 列举jedis常见问题及redis缓存使用规范,值得读。

当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--​​buguge



举报

相关推荐

0 条评论