• JedisPool使用原理和源代码


    1,JedisPool的使用

    <!-- 连接池的配置信息 --><beanid="jedisConfig"class="redis.clients.jedis.JedisPoolConfig"><!-- 说明一个pool可以有多少个Jedis实例 --><propertyname="maxActive"value="10" /><!-- 最大Idle--><propertyname="maxIdle"value="5" /><!-- 最小Idle --><propertyname="minIdle"value="1" /><!-- 获得一个jedis实例的时候是否检查连接可用性(ping()) --><propertyname="testOnBorrow"value="true" /><!-- return 一个jedis实例给pool时,是否检查连接可用性(ping()) --><propertyname="testOnReturn"value="true" /><!-- idle状态监测用异步线程evict进行检查, --><propertyname="testWhileIdle"value="true" /><!-- 一次最多evict的pool里的jedis实例个数 --><propertyname="numTestsPerEvictionRun"value="10" /><!-- test idle 线程的时间间隔 --><propertyname="timeBetweenEvictionRunsMillis"value="60000" /><!--最大等待wait时间--><propertyname="maxWait"value="3000" /><propertyname="whenExhaustedAction"value="" />
        //WHEN_EXHAUSTED_FAIL = 0; 直接抛出异常throw new NoSuchElementException("Pool exhausted");
        //WHEN_EXHAUSTED_BLOCK = 1;borrowObject()将会阻塞,直到有可用新的或者空闲的object为止,或者如果配置了maxWait,
                                //如果请求阻塞超时,将抛出NoSuchElementException.如果maxWait为负数,请求将会无限制的阻
                                //塞下去,默认配置。
        //WHEN_EXHAUSTED_GROW = 2;borrowObject()将会继续创建新的对象,并返回,因此,pool维护的对像数将超出maxActive;
                                //
    </bean>
     
     
    public String set(String key, String value) {
        Jedis jedis = null;
        boolean success = true;
        try {
            jedis = this.pool.getResource();
            return jedis.set(key, value);
        }catch (JedisException e) {
            success  = false;
            if(jedis != null){
                pool.returnBrokenResource(jedis);
            }
            throw e;
        }finally{
            if(success && jedis != null){
                this.pool.returnResource(jedis);
            }
        }
    }

    获取Jedis

    pool.getResource();

    这个可以直接看Pool的getResource方法,

    最终还是GenericObjectPool的borrowObject()方法借用对象

    @SuppressWarnings("unchecked")
    public T getResource() {
        try {
            return (T) internalPool.borrowObject();
        } catch (Exception e) {
            throw new JedisConnectionException(
                    "Could not get a resource from the pool", e);
        }
    }

    用完归还,调用的是GenericObjectPool的returnObject()方法

    pool.returnResource(jedis)
    //JedisPool.java
    public void returnResource(final BinaryJedis resource) {
        returnResourceObject(resource);
    }
    //Pool.java
    publicvoid returnResourceObject(final Object resource) {
    try {
        internalPool.returnObject(resource);
    } catch (Exception e) {
        throw new JedisException(
                "Could not return the resource to the pool", e);
    }
    }

    出错,调用的是GenericObjectPool的invalidateObject()方法

    最后在JedisFactory的destroyObject()中调用jedis.quit()请求Server关闭连接

    pool.returnBrokenResource(jedis)
    //JedisPool.java
    public void returnBrokenResource(final BinaryJedis resource) {
        returnBrokenResourceObject(resource);
    }
    //Pool.javaprotectedvoid returnBrokenResourceObject(final Object resource) {
        try {
            //失效
            internalPool.invalidateObject(resource);
        } catch (Exception e) {
            thrownew JedisException(
                    "Could not return the resource to the pool", e);
        }
    }
    //GenericObjectPool
    publicvoid invalidateObject(Object obj)
    throws Exception
    {
    try
    {
      if (this._factory != null)
        this._factory.destroyObject(obj);
    }
    finally {
      synchronized (this) {
        this._numActive -= 1;
        allocate();
      }
    }
    }
    //JedisFactory
    publicvoid destroyObject(final Object obj) throws Exception {
        if (obj instanceof Jedis) {
            final Jedis jedis = (Jedis) obj;
            if (jedis.isConnected()) {
                try {
                    try {
                        jedis.quit();
                    } catch (Exception e) {
                    }
                    jedis.disconnect();
                } catch (Exception e) {
    
                }
            }
        }
    }

    JedisPool源代码

    package redis.clients.jedis;
    
    import org.apache.commons.pool.BasePoolableObjectFactory;
    import org.apache.commons.pool.impl.GenericObjectPool.Config;
    
    import redis.clients.util.Pool;
    
    publicclassJedisPoolextendsPool<Jedis> {public JedisPool(final Config poolConfig, final String host) {
            this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
        }
    
        public JedisPool(String host, int port) {
            this(new Config(), host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
        }
    
        public JedisPool(final String host) {
            this(host, Protocol.DEFAULT_PORT);
        }
    
        public JedisPool(final Config poolConfig, final String host, int port,
                int timeout, final String password) {
            this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE);
        }
    
        public JedisPool(final Config poolConfig, final String host, finalint port) {
            this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);
        }
    
        public JedisPool(final Config poolConfig, final String host, finalint port, finalint timeout) {
            this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE);
        }
    
        public JedisPool(final Config poolConfig, final String host, int port, int timeout, final String password,
                         finalint database) {
            super(poolConfig, new JedisFactory(host, port, timeout, password, database));
        }
    
    
        publicvoid returnBrokenResource(final BinaryJedis resource) {
            returnBrokenResourceObject(resource);
        }
    
        publicvoid returnResource(final BinaryJedis resource) {
            returnResourceObject(resource);
        }
    
        /**
         * PoolableObjectFactory custom impl.
         */privatestaticclassJedisFactoryextendsBasePoolableObjectFactory {privatefinal String host;
            privatefinalint port;
            privatefinalint timeout;
            privatefinal String password;
            privatefinalint database;
    
            public JedisFactory(final String host, finalint port,
                    finalint timeout, final String password, finalint database) {
                super();
                this.host = host;
                this.port = port;
                this.timeout = timeout;
                this.password = password;
                this.database = database;
            }
    
            public Object makeObject() throws Exception {
                final Jedis jedis = new Jedis(this.host, this.port, this.timeout);
    
                jedis.connect();
                if (null != this.password) {
                    jedis.auth(this.password);
                }
                if( database != 0 ) {
                    jedis.select(database);
                }
    
                return jedis;
            }
    
            publicvoid destroyObject(final Object obj) throws Exception {
                if (obj instanceof Jedis) {
                    final Jedis jedis = (Jedis) obj;
                    if (jedis.isConnected()) {
                        try {
                            try {
                                jedis.quit();
                            } catch (Exception e) {
                            }
                            jedis.disconnect();
                        } catch (Exception e) {
    
                        }
                    }
                }
            }
    
            publicboolean validateObject(final Object obj) {
                if (obj instanceof Jedis) {
                    final Jedis jedis = (Jedis) obj;
                    try {
                        return jedis.isConnected();/* && jedis.ping().equals("PONG");*/
                    } catch (final Exception e) {
                        returnfalse;
                    }
                } else {
                    returnfalse;
                }
            }
        }
    }

    其中JedisFactory继承自BasePoolableObjectFactory,只实现了3个方法

    makeObject(),连接,new Socket()

    destroyObject()--断开连接,

    validateObject()--ping

    
    
    
    

    Pool源代码

    package redis.clients.util;
    
    import org.apache.commons.pool.PoolableObjectFactory;
    import org.apache.commons.pool.impl.GenericObjectPool;
    
    import redis.clients.jedis.exceptions.JedisConnectionException;
    import redis.clients.jedis.exceptions.JedisException;
    
    publicabstractclassPool<T> {privatefinal GenericObjectPool internalPool;
    
        public Pool(final GenericObjectPool.Config poolConfig,
                PoolableObjectFactory factory) {
            this.internalPool = new GenericObjectPool(factory, poolConfig);
        }
    
        @SuppressWarnings("unchecked")
        public T getResource() {
            try {
                return (T) internalPool.borrowObject();
            } catch (Exception e) {
                thrownew JedisConnectionException(
                        "Could not get a resource from the pool", e);
            }
        }
    
        publicvoid returnResourceObject(final Object resource) {
            try {
                internalPool.returnObject(resource);
            } catch (Exception e) {
                thrownew JedisException(
                        "Could not return the resource to the pool", e);
            }
        }
    
        publicvoid returnBrokenResource(final T resource) {
            returnBrokenResourceObject(resource);
        }
    
        publicvoid returnResource(final T resource) {
            returnResourceObject(resource);
        }
    
        protectedvoid returnBrokenResourceObject(final Object resource) {
            try {
                //失效
                internalPool.invalidateObject(resource);
            } catch (Exception e) {
                thrownew JedisException(
                        "Could not return the resource to the pool", e);
            }
        }
    
        publicvoid destroy() {
            try {
                internalPool.close();
            } catch (Exception e) {
                thrownew JedisException("Could not destroy the pool", e);
            }
        }
    }

    JedisPoolConfig源代码

    publicclassJedisPoolConfigextendsConfig {public JedisPoolConfig() {
            // defaults to make your life with connection pool easier :)
            setTestWhileIdle(true);
            setMinEvictableIdleTimeMillis(60000);
            setTimeBetweenEvictionRunsMillis(30000);
            setNumTestsPerEvictionRun(-1);
        }
    
        publicint getMaxIdle() {
            return maxIdle;
        }
    
        publicvoid setMaxIdle(int maxIdle) {
            this.maxIdle = maxIdle;
        }
    
        publicint getMinIdle() {
            return minIdle;
        }
    
        publicvoid setMinIdle(int minIdle) {
            this.minIdle = minIdle;
        }
    
        publicint getMaxActive() {
            return maxActive;
        }
    
        publicvoid setMaxActive(int maxActive) {
            this.maxActive = maxActive;
        }
    
        publiclong getMaxWait() {
            return maxWait;
        }
    
        publicvoid setMaxWait(long maxWait) {
            this.maxWait = maxWait;
        }
    
        publicbyte getWhenExhaustedAction() {
            return whenExhaustedAction;
        }
    
        publicvoid setWhenExhaustedAction(byte whenExhaustedAction) {
            this.whenExhaustedAction = whenExhaustedAction;
        }
    
        publicboolean isTestOnBorrow() {
            return testOnBorrow;
        }
    
        publicvoid setTestOnBorrow(boolean testOnBorrow) {
            this.testOnBorrow = testOnBorrow;
        }
    
        publicboolean isTestOnReturn() {
            return testOnReturn;
        }
    
        publicvoid setTestOnReturn(boolean testOnReturn) {
            this.testOnReturn = testOnReturn;
        }
    
        publicboolean isTestWhileIdle() {
            return testWhileIdle;
        }
    
        publicvoid setTestWhileIdle(boolean testWhileIdle) {
            this.testWhileIdle = testWhileIdle;
        }
    
        publiclong getTimeBetweenEvictionRunsMillis() {
            return timeBetweenEvictionRunsMillis;
        }
    
        publicvoid setTimeBetweenEvictionRunsMillis(
                long timeBetweenEvictionRunsMillis) {
            this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        }
    
        publicint getNumTestsPerEvictionRun() {
            return numTestsPerEvictionRun;
        }
    
        publicvoid setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
            this.numTestsPerEvictionRun = numTestsPerEvictionRun;
        }
    
        publiclong getMinEvictableIdleTimeMillis() {
            return minEvictableIdleTimeMillis;
        }
    
        publicvoid setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
            this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
        }
    
        publiclong getSoftMinEvictableIdleTimeMillis() {
            return softMinEvictableIdleTimeMillis;
        }
    
        publicvoid setSoftMinEvictableIdleTimeMillis(
                long softMinEvictableIdleTimeMillis) {
            this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
        }
    
    }

     

  • 相关阅读:
    在ASP.NET 5中使用SignalR
    直传文件到Azure Storage的Blob服务中
    利用IdentityServer3在ASP.NET 5和Angular中实现OAuth2 Implicit Flow
    【IDEA】如何设置代码超出长度限制时自动换行
    【IEDA】Typo: In woed 'xxx' more...(Ctrl + F1) 拼写检查
    【IDEA】URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs
    【IDEA】创建的 maven 项目,右键 New --> XML Configuration File 时,无 Spring Config 选项
    RHEL8网络配置
    Python GUI界面编程-初识
    Deepin系统中如何安装Visual Studio Code
  • 原文地址:https://www.cnblogs.com/lsx1993/p/4619945.html
Copyright © 2020-2023  润新知