背景
分布式缓存连接池版Java客户端,在redis官方java客户端Jedis的基础上进行了封装,针对分布式缓存存在多个接入机的模式,建立并维护与多接入机的连接池(同步连接),支持:
(1)多接入机模式下的连接池操作,可配置多接入机地址,采用轮询方式发送命令至接入机集群。
(2)完全兼容jedis,可直接使用官方客户端Jedis的操作。
(3)客户端可动态监测服务端可用状态来调整获取连接策略。
(4)支持最大连接数、最大/最小空闲连接数、监测开闭、后台监测周期等多项参数的配置。
通过全国各省IT推广的运维经验,建议单个应用使用单个连接池,而不是单个应用使用多个连接池(会导致总体连接数较高,浪费资源)。
开发相关配置
- 项目配置
- Maven-pom配置
注意:2.3.2版本以后,Java连接池版客户端依赖ctg-cache-nclient,不再依赖ctg-cache-control,新版的nclient中jedis请使用3.3.0。<dependency> <groupId>com.ctg.itrdc.cache</groupId> <artifactId>ctg-cache-nclient</artifactId> <version>2.8.4</version> </dependency>
<distributionManagement> <repository> <id>releases</id> <name>Internal Releases</name> <url>http://10.142.90.61:8081/nexus/content/repositories/releases</url> </repository> <snapshotRepository> <id>snapshots</id> <name>Internal Snapshots</name> <url>http://10.142.90.61:8081/nexus/content/repositories/snapshots</url> </snapshotRepository> </distributionManagement>
- 配置项
需要设置如下两个配置类,其中后者是前者的变量。
CtgJedisPoolConfig 包含客户端所有配置项
参数 类型 说明 poolConfig
GenericObjectPoolConfig
Apache pool 配置,默认为JedisPoolConfig
connectionTimeout
int
连接超时时间,单位毫秒,默认5秒
soTimeout
int
操作超时时间,单位毫秒,默认5秒
password
String
密码,必填,格式为“用户#密码”
database
Int/String
桶位或者分组名,必填
clientName
String
客户端名,默认null
period
long
后台监控执行周期,毫秒,默认3秒
monitorTimeout
int
监控命令超时时间,毫秒,默认500毫秒
monitorErrorNum
int
监控连续出错几次,将接入机节点判断为失效,默认3次
nodes
List<HostAndPort>
接入机地址列表
monitorLog
boolean
是否开启后台监控日志,默认开启
GenericObjectPoolConfig 封装了与连接池有关配置
参数 类型 说明 MaxTotal
int
最大连接数(空闲+使用中),建议设置为应用线程数的一半到应用的线程总数的范围内。
MaxIdle
int
最大空闲连接数,不超过最大连接数
MinIdle
int
保持的最小空闲连接数,默认0
MaxWaitMillis
long
获取连接时的最大等待毫秒数,如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
TestWhileIdle
boolean
在空闲时检查有效性,默认true
MinEvictableIdleTimeMillis
long
逐出连接的最小空闲时间(毫秒),默认60秒
TimeBetweenEvictionRunsMillis
long
逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认30秒
NumTestsPerEvictionRun
int
每次逐出检查时 逐出的最大数目百分比,如果是负数,则为1/abs(n),默认为-1
- 配置操作连接池对象的实例化需要CtgJedisPoolConfig配置类,CtgJedisPoolConfig配置类中的参数可参考上述表格,其中(GenericObjectPoolConfig)poolConfig变量用于配置客户端与接入机的连接池参数,类JedisPoolConfig继承自GenericObjectPoolConfig并设置了合理的默认参数。所以在配置操作时,CtgJedisPoolConfig中的poolConfig参数推荐使用类JedisPoolConfig实现,并设置额外的配置。参考代码如下:
List<HostAndPort> hostAndPortList = new ArrayList(); // 接入机的ip和端口号 HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362 ); hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(10); //最大连接数(空闲+使用中),建议设置为应用线程数的一半到应用的线程总数的范围内。 poolConfig.setMaxIdle(10); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255)//分组名或者db .setPassword("pool#Jedis*123") // 实例名#密码 .setPoolConfig(poolConfig) .setPeriod(3000) .setMonitorTimeout(200);
- Maven-pom配置
- 连接池操作
- 创建连接池CtgJedisPool
入参说明:CtgJedisPool pool = new CtgJedisPool(config);
参数
类型
是否可为空
说明
config
CtgJedisPoolConfig
N
连接池配置数据
List<HostAndPort> hostAndPortList = new ArrayList(); HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362 ); hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(10); // 最大连接数(空闲+使用中) poolConfig.setMaxIdle(5); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255).setPassword("pool#Jedis*123").setPoolConfig(poolConfig) .setPeriod(3000).setMonitorTimeout(200); CtgJedisPool pool = new CtgJedisPool(config);
-
销毁连接池close
(CtgJedisPool)pool.close();
功能描述:销毁连接池,可能会抛出运行时异常:
示例throw new JedisException("Could not destroy the pool", e);
CtgJedisPool pool = new CtgJedisPool(config); pool.close();
- 获取连接getResource
(CtgJedisPool)pool.getResource();
功能描述:从连接池中获取一个可用连接,客户端会轮询可用列表从中拿出可用连接,使用完成后请使用归还命令归还连接。
注意事项:获取失败会抛出异常CtgJedisPoolException
返回类型:ProxyJedis示例
initPool(); ProxyJedis jedis = new ProxyJedis(); try { jedis = pool.getResource(); String key = StringGenarator.getRandomKeyString(10); String value = StringGenarator.getRandomValueString(10); //sendCommand 可能会抛出 运行时异常 jedis.set(key, value); //sendCommand 可能会抛出 运行时异常 jedis.get(key); jedis.close(); } catch (Throwable je){ jedis.close(); } pool.close();
- 归还连接jedis.close()
功能描述:将连接归还至连接池中,如果使用过程发生异常、超时,将会销毁该连接(ProxyJedis)jedis.close();
示例
initPool(); ProxyJedis jedis = new ProxyJedis(); try { jedis = pool.getResource(); String key = StringGenarator.getRandomKeyString(10); String value = StringGenarator.getRandomValueString(10); //sendCommand 可能会抛出 运行时异常 jedis.set(key, value); //sendCommand 可能会抛出 运行时异常 jedis.get(key); jedis.close(); } catch (Throwable je){ jedis.close(); } pool.close();
- 创建连接池CtgJedisPool
- 其他说明
(1)密码与桶位在初始化连接池时使用,后期不可修改。
(2)获取连接后及时归还连接,使用过程中发生异常catch后要归还连接。
(3)GenericObjectPoolConfig配置的连接池数量是与所有接入机连接数之和,请参考Apache Commons pool2合理配置。
(4)类JedisPoolConfig继承自GenericObjectPoolConfig并设置了合理的默认参数,推荐使用JedisPoolConfig作为配置。
(5)查问题时请先跟踪连接池客户端的监控日志,判断接入机状况;
(6)单个连接只能单线程调用,不可多线程复用。
- 示例代码
public class CtgJedisPoolTest { public static final Logger logger = LoggerFactory.getLogger(CtgJedisPoolTest.class); public static void main(String[] args) { BasicConfigurator.configure(); List<HostAndPort> hostAndPortList = new ArrayList(); //接入机地址列表 HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); //接入机-1 HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362); //接入机-2 hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); //线程池配置 poolConfig.setMaxTotal(10); // 最大连接数(空闲+使用中) poolConfig.setMaxIdle(3); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); //借出连接时最大的等待时间 CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255) //分组对应的桶位 .setPassword("pool#Jedis*123") // “用户#密码” .setPoolConfig(poolConfig) //线程池配置 .setPeriod(3000) //后台监控执行周期,毫秒 .setMonitorTimeout(200); //后台监控ping命令超时时间,毫秒 CtgJedisPool pool = new CtgJedisPool(config); //创建连接池 ProxyJedis jedis = null; for (int i = 1; i <= 1000; i++) { try { jedis = pool.getResource(); //获取连接,可能抛出异常 String key = "**key" +i; String value = "**value" + i; jedis.set(key, value); } catch (CtgJedisPoolException e) { logger.error(e.getMessage(), e); } catch (JedisConnectionException e) { logger.error(e.getMessage(), e); } finally { // finally内执行,确保连接归还 try{ jedis.close(); } catch (Throwable e) { } //归还连接至连接池 } } pool.close(); //关闭连接池 } }