前段时间公司的项目运行一段时间后出现宕机状态,静态页面虽能打开,但是请求都无法成功。
查看日志,发现请求卡在Opening RedisConnection就不往下走了

看代码,拦截器中有做redis操作,而不知为何redis操作不往下走了
查看源码,jedis没有配置最大等待时间,而默认配置 blockWhenExhausted=true ,获取不到资源会一直阻塞等待
PooledObject<T> p = null; // Get local copy of current config so it is consistent for entire // method execution //默认配置为true,资源耗尽阻塞 final boolean blockWhenExhausted = getBlockWhenExhausted(); boolean create; final long waitTime = System.currentTimeMillis(); while (p == null) { create = false; p = idleObjects.pollFirst();//从空闲队列弹出PooledObject if (p == null) { //如果为空,则创建,如果超过最大数,则返回空 p = create(); if (p != null) { create = true; } } if (blockWhenExhausted) { if (p == null) { if (borrowMaxWaitMillis < 0) { //如果没有配置maxWaitMillis,则去idleObjects等待资源,如果没有空闲资源就阻塞一直等待 p = idleObjects.takeFirst(); } else { //如果配置了maxWaitMillis,则超时返回 p = idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS); } } if (p == null) { throw new NoSuchElementException( "Timeout waiting for idle object"); } } else { if (p == null) { throw new NoSuchElementException("Pool exhausted"); } } }
于是增加配置
<property name="maxWaitMillis" value="3000"/>
改了后,这回项目不会阻塞了,但是运行一段时间后,会频繁的报错,Could not get a resource from the pool
去网上找了一大圈都不靠谱,还是得自己调试找原因
想想项目中使用redis的情况,感觉一切都很正常,唯一有点值得注意的是
<property name="enableTransactionSupport" value="true" />
public static void releaseConnection(RedisConnection conn, RedisConnectionFactory factory) { if (conn == null) { return; } RedisConnectionHolder connHolder = (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory); if (connHolder != null && connHolder.isTransactionSyncronisationActive()) { if (log.isDebugEnabled()) { log.debug("Redis Connection will be closed when transaction finished."); } return; } // release transactional/read-only and non-transactional/non-bound connections. // transactional connections for read-only transactions get no synchronizer registered //如果配置了enableTransactionSupport=true,以下条件都不满足,连接没有释放 if (isConnectionTransactional(conn, factory) && TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { unbindConnection(factory); } else if (!isConnectionTransactional(conn, factory)) { if (log.isDebugEnabled()) { log.debug("Closing Redis Connection"); } conn.close(); } }
于是idleobjects的size一直为0,pool会新建PooledObject,等到一段时间后,达到最大资源数,便无法从pool中获取到资源
尝试手动释放资源,果然就可以了
public boolean hasKey(final String key) { try { return redisTemplate.hasKey(key); } finally { //释放连接 RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory()); } }
参考
(中文) http://www.cnblogs.com/qijiang/p/5626461.html
(原文) https://www.javaworld.com/article/3062899/big-data/lightning-fast-nosql-with-spring-data-redis.html?page=2