Jedis Pool使用原理及源码

来源:互联网 发布:天猫刷流量软件 编辑:程序博客网 时间:2024/05/28 09:34

1,JedisPool的使用

<!-- 连接池的配置信息 --><bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">  <!-- 说明一个pool可以有多少个Jedis实例 -->  <property name="maxActive" value="10" />  <!-- 最大Idle-->  <property name="maxIdle" value="5" />  <!-- 最小Idle -->  <property name="minIdle" value="1" />  <!-- 获得一个jedis实例的时候是否检查连接可用性(ping()) -->  <property name="testOnBorrow" value="true" />  <!-- return 一个jedis实例给pool时,是否检查连接可用性(ping()) -->  <property name="testOnReturn" value="true" />  <!-- idle状态监测用异步线程evict进行检查, -->  <property name="testWhileIdle" value="true" />  <!-- 一次最多evict的pool里的jedis实例个数 -->  <property name="numTestsPerEvictionRun" value="10" />  <!-- test idle 线程的时间间隔 -->  <property name="timeBetweenEvictionRunsMillis" value="60000" />  <!--最大等待wait时间-->  <property name="maxWait" value="3000" />  <property name="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.javapublic void returnResource(final BinaryJedis resource) {    returnResourceObject(resource);}//Pool.javapublic void 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.javapublic void returnBrokenResource(final BinaryJedis resource) {    returnBrokenResourceObject(resource);}//Pool.javaprotected void returnBrokenResourceObject(final Object resource) {    try {        //失效        internalPool.invalidateObject(resource);    } catch (Exception e) {        throw new JedisException(                "Could not return the resource to the pool", e);    }}//GenericObjectPoolpublic void invalidateObject(Object obj)throws Exception{try{  if (this._factory != null)    this._factory.destroyObject(obj);}finally {  synchronized (this) {    this._numActive -= 1;    allocate();  }}}//JedisFactorypublic void 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;public class JedisPool extends Pool<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, final int port) {        this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE);    }    public JedisPool(final Config poolConfig, final String host, final int port, final int 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,                     final int database) {        super(poolConfig, new JedisFactory(host, port, timeout, password, database));    }    public void returnBrokenResource(final BinaryJedis resource) {        returnBrokenResourceObject(resource);    }    public void returnResource(final BinaryJedis resource) {        returnResourceObject(resource);    }    /**     * PoolableObjectFactory custom impl.     */    private static class JedisFactory extends BasePoolableObjectFactory {        private final String host;        private final int port;        private final int timeout;        private final String password;        private final int database;        public JedisFactory(final String host, final int port,                final int timeout, final String password, final int 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;        }        public void 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) {                    }                }            }        }        public boolean 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) {                    return false;                }            } else {                return false;            }        }    }}

其中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;public abstract class Pool<T> {    private final 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) {            throw new JedisConnectionException(                    "Could not get a resource from the pool", e);        }    }    public void returnResourceObject(final Object resource) {        try {            internalPool.returnObject(resource);        } catch (Exception e) {            throw new JedisException(                    "Could not return the resource to the pool", e);        }    }    public void returnBrokenResource(final T resource) {        returnBrokenResourceObject(resource);    }    public void returnResource(final T resource) {        returnResourceObject(resource);    }    protected void returnBrokenResourceObject(final Object resource) {        try {            //失效            internalPool.invalidateObject(resource);        } catch (Exception e) {            throw new JedisException(                    "Could not return the resource to the pool", e);        }    }    public void destroy() {        try {            internalPool.close();        } catch (Exception e) {            throw new JedisException("Could not destroy the pool", e);        }    }}
JedisPoolConfig源代码

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

原创粉丝点击