springboot自动装配redis在pool下偶尔出现链接异常的问题

jedis pool的配置实际上是采用 org.apache.commons.pool2.impl.GenericObjectPoolConfig类的配置项。redis

jedis 2.9版本代码以下:spring

package redis.clients.jedis;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class JedisPoolConfig extends GenericObjectPoolConfig {
  public JedisPoolConfig() {
    // defaults to make your life with connection pool easier :)
    setTestWhileIdle(true);
    setMinEvictableIdleTimeMillis(60000);
    setTimeBetweenEvictionRunsMillis(30000);
    setNumTestsPerEvictionRun(-1);
  }
}

而springboot的自动装配中对redis链接池的配置:数据库

代码位置:org.springframework.boot.autoconfigure.data.redis.RedisProperties.Poolapache

/**
     * Pool properties.
     */
    public static class Pool {

        /**
         * Max number of "idle" connections in the pool. Use a negative value to indicate
         * an unlimited number of idle connections.
         */
        private int maxIdle = 8;

        /**
         * Target for the minimum number of idle connections to maintain in the pool. This
         * setting only has an effect if it is positive.
         */
        private int minIdle = 0;

        /**
         * Max number of connections that can be allocated by the pool at a given time.
         * Use a negative value for no limit.
         */
        private int maxActive = 8;

        /**
         * Maximum amount of time (in milliseconds) a connection allocation should block
         * before throwing an exception when the pool is exhausted. Use a negative value
         * to block indefinitely.
         */
        private int maxWait = -1;

        public int getMaxIdle() {
            return this.maxIdle;
        }

        public void setMaxIdle(int maxIdle) {
            this.maxIdle = maxIdle;
        }

        public int getMinIdle() {
            return this.minIdle;
        }

        public void setMinIdle(int minIdle) {
            this.minIdle = minIdle;
        }

        public int getMaxActive() {
            return this.maxActive;
        }

        public void setMaxActive(int maxActive) {
            this.maxActive = maxActive;
        }

        public int getMaxWait() {
            return this.maxWait;
        }

        public void setMaxWait(int maxWait) {
            this.maxWait = maxWait;
        }

    }

问题就出现了:经过spring.redis.pool.xxx的自动装配的配置key其实就比jedis的pool的配置key要少不少,当redis服务端设置了链接空闲的最大时间时,redis服务会kill掉符合条件的空闲的连接,此时客户端的链接池并不会感知链接被kill,当有代码调用pool获取链接时可能会返回一个失效的链接对象,从而致使代码报错。springboot

解决方案:不使用默认的装配。性能

 JedisPoolConfig config = new JedisPoolConfig();// 最小空闲链接数config.setMinIdle(props.getMinIdle());this

// 最大空闲链接数 config.setMaxIdle(props.getMaxIdle()); // 链接池最大链接数 config.setMaxTotal(props.getMaxActive()); // 最大创建链接等待时间。若是超过此时间将接到异常。设为-1表示无限制。 config.setMaxWaitMillis(props.getMaxWait()); // 在空闲时检查有效性 config.setTestWhileIdle(props.isTestWhileIdle()); // 是否在从池中取出链接前进行检验,若是检验失败,则从池中去除链接并尝试取出另外一个 config.setTestOnBorrow(props.isTestOnBorrow()); // 在return给pool时,是否提早进行validate操做 config.setTestOnReturn(props.isTestOnReturn()); // 表示一个对象至少停留在idle状态的最短期,而后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义 // 该值参考redis server的配置来进行配置 config.setMinEvictableIdleTimeMillis(props.getTimeout()); // 表示idle object evitor两次扫描之间的间隔时间,-1表示不开启这个task config.setTimeBetweenEvictionRunsMillis(props.getTimeout()/2); // 表示idle object evitor每次扫描的最多的对象数
// 建议设置和maxTotal同样大,这样每次能够有效检查全部的连接.
config.setNumTestsPerEvictionRun(props.getNumTestsPerEvictionRun());

 注意:timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis的总和应小于 数据库设置的 超时空闲失效时间spa

若是将 testOnBorrow 和 testOnReturn设置为true将会加剧服务的负担,下降服务的性能,最好是经过合理的配置 testWhileIdle、minEvictableIdleTimeMillis、timeBetweenEvictionRunsMillis、numTestsPerEvictionRun来达到达到失效链接的清除工做。code

相关文章
相关标签/搜索