JedisPool使用原理及源代码
2013-12-26 12:37
369 查看
1,JedisPool的使用
[code]<!-- 连接池的配置信息 --> <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>
[code]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
[code]pool.getResource();
这个可以直接看Pool的getResource方法,
最终还是GenericObjectPool的borrowObject()方法借用对象
[code]@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()方法
[code]pool.returnResource(jedis) //JedisPool.java public void returnResource(final BinaryJedis resource) { returnResourceObject(resource); } //Pool.java 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); } }
出错,调用的是GenericObjectPool的invalidateObject()方法
最后在JedisFactory的destroyObject()中调用jedis.quit()请求Server关闭连接
[code]pool.returnBrokenResource(jedis) //JedisPool.java public void returnBrokenResource(final BinaryJedis resource) { returnBrokenResourceObject(resource); } //Pool.java 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); } } //GenericObjectPool public void invalidateObject(Object obj) throws Exception { try { if (this._factory != null) this._factory.destroyObject(obj); } finally { synchronized (this) { this._numActive -= 1; allocate(); } } } //JedisFactory 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) { } } } }
JedisPool源代码
[code]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
[code]
Pool源代码
[code]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源代码
[code]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; } }
[/code]
相关文章推荐
- JedisPool使用原理和源代码
- JAVA多线程顺序执行(使用join,lock,condition,信号量)原理和java源代码
- 【源代码】手把手教你Autolayout如何使用动画(附类似Passbook效果Demo+详细分析实现原理)
- Android中IntentService的原理及使用
- Consul 原理和使用简介
- AFNetworking的原理与基本使用
- ZooKeeper原理及使用
- Android中IntentService的原理及使用
- SQL游标原理和使用方法
- ButterKnife框架原理和使用
- Android中CursorLoader的使用、原理及注意事项
- 源代码解读Cas实现单点登出(single sign out)功能实现原理--转
- CCTextureCache的多线程加载原理和使用
- Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结
- IOS SEL (@selector)原理及使用总结
- kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
- ThinkPHP中URL解析原理,以及URL路由使用教程!
- IOS SEL (@selector) 原理及使用总结(一)
- android线程池的使用方法和原理
- Struts2之拦截器原理分析及使用-下