java连接池的maxIdle该如何配置

摘要:最近针对某系统做了次压力测试,在并发较高的时候暴露了一个maxIdle设置不合理的问题,特总结一下这次问题,并分析一下这个问题背后的原因。

问题现象

60个线程并发访问某个读和写均有的业务接口,性能测试人员查看Oracle数据库负载CPU非常高,而且oracleLogons指标达到148.1/秒(这个值的含义是数据库客户端登录认证的每秒的次数)。





而且查看应用程序中的线程栈,也发现了较多数量的线程处于创建新的oracle物理连接处。



这当时就让我有点儿糊涂了,我们不是用了连接池吗?怎么还会经常创建物理连接呢?

问题分析解决

遇到这个问题,我当时也是从自己掌握的各种知识里去想可能的原因,都想到了是不是因为tcp连接的超时时间是不是太短,仔细一想这些可能性都排除掉了。然后查看连接池的配置,当时我们的同学告诉我这些配置跟线上的是一样的,应该没有问题,我当时是就怀疑是maxIdle设置太小导致的原因,但是没有什么具体的依据。

所以我就简单开发了一个页面可以实时查看当时应用连接池的active number(当前被使用的数据库连接数)和idle number(当前处于空闲状态的数据库连接数)。再次运行测试脚本,通过查看连接池的连接数就可以看出来,连接数的波动较大,有时候连接总数(上面两个数字相加)从20多突然降到10,说明物理连接被销毁了,创建了新的物理连接,那这就与我们看到的一些异常现象相吻合了,创建新的连接就会导致oracle数据库服务器的logons数量增加。由于连接的复用率较差,导致频繁的创建物理连接,oracle数据库的资源消耗增大。

网上找到一篇文章详细介绍dbcp连接池配置的,它关于maxIdle的配置说明是这么写的。

 

maxIdle值与maxActive值应配置的接近。 因为,当连接数超过maxIdle值后,刚刚使用完的连接(刚刚空闲下来)会立即被销毁。而不是我想要的空闲M秒后再销毁起一个缓冲作用。这一点DBCP做的可能与你想像的不一样。 若maxIdle与maxActive相差较大,在高负载的系统中会导致频繁的创建、销毁连接,连接数在maxIdle与maxActive间快速频繁波动,这不是我想要的。 高负载系统的maxIdle值可以设置为与maxActive相同或设置为-1(-1表示不限制),让连接数量在minIdle与maxIdle间缓冲慢速波动。

原文参考: http://elf8848.iteye.com/blog/1931778

 

看到这个我明白了因为我们的配置是maxIdle配置的值是5,而maxActive配置的值为40,这样当并发较高的时候,当连接数接近maxActive值的情况下,空闲连接数很容易超过maxIdle,很快就被连接池给主动销毁了,这样就导致了连接频繁的创建,弱化了数据库连接池的作用。

这次的性能测试然让我深刻的感受到了数据库连接池对的价值,使用得当,它能够很好地复用已有的物理连接,在高并发的场景下,减少频繁的创建和销毁物理连接,降低系统的压力。用得不好,它的价值就发挥不出来,就像咱们今天这个案例一样。

 

为什么是这样的?

maxIdle的值为什么要与maxActive的接近呢?果真如此吗?我们还要通过源码来分析它背后的根本原因。



看看上图是对dbcp连接池的获取和归还连接对象的流程图的描述,通过该图我们就一目了然了。

详细的原理和源码分析请看这里:http://www.myexception.cn/apache/1874092.html

maxIdle配置总结

maxIdle值与maxActive值应配置的接近。

因为,当连接数超过maxIdle值后,刚刚使用完的连接(刚刚空闲下来)会立即被销毁。而不是我想要的空闲M秒后再销毁起一个缓冲作用。这一点DBCP做的可能与你想像的不一样。

maxIdlemaxActive相差较大,在高负载的系统中会导致频繁的创建、销毁连接,连接数在maxIdlemaxActive间快速频繁波动,这不是我们想要的。

高负载系统的maxIdle值可以设置为与maxActive相同或设置为-1(-1表示不限制),让连接数量在minIdlemaxIdle间缓冲慢速波动。多余的空闲连接等待回收线程来缓慢回收。

 

至于具体多少合理取决于大家的具体应用场景,但是配置的原则是这样的:

1.如果是连接池命中率(即应用在获取连接时直接获得已经创建物理连接的比率)优先的应用。适合连接资源较充裕的环境,可以尽可能将maxIdle设置得更大一些,多数应用设置的大一些会更加安全。

2.如果是连接资源利用率(即被使用连接占的比率)优先的应用。适合那些连接资源紧张的环境。可以尽可能将maxIdle设置得更小一些,这样空闲连接能够得到更快的释放,保持一个较小的连接,但是设置的过小的话会导致连接池命中率非常低,弱化连接池的作用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ctgjedispool是一个基于Jedis实现的连接池库,可以用来连接Redis数据库。 以下是ctgjedispool连接池配置步骤: 1. 添加ctgjedispool依赖 在项目的pom.xml文件中添加以下依赖: ``` <dependency> <groupId>com.ctgjedispool</groupId> <artifactId>ctgjedispool</artifactId> <version>1.0.0</version> </dependency> ``` 2. 配置连接池参数 在项目的配置文件中,添加以下连接池参数: ``` #Redis服务器地址 redis.host=127.0.0.1 #Redis服务器端口 redis.port=6379 #Redis服务器密码 redis.password=123456 #连接池最大连接数 redis.maxTotal=500 #连接池最大空闲连接数 redis.maxIdle=10 #连接池最小空闲连接数 redis.minIdle=2 #获取连接时的最大等待毫秒数 redis.maxWaitMillis=10000 #在获取连接的时候检查有效性,默认为false redis.testOnBorrow=false #在归还连接的时候检查有效性,默认为false redis.testOnReturn=false ``` 3. 创建连接池Java代码中,使用以下代码创建连接池: ``` JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(Integer.parseInt(env.getProperty("redis.maxTotal"))); config.setMaxIdle(Integer.parseInt(env.getProperty("redis.maxIdle"))); config.setMinIdle(Integer.parseInt(env.getProperty("redis.minIdle"))); config.setMaxWaitMillis(Integer.parseInt(env.getProperty("redis.maxWaitMillis"))); config.setTestOnBorrow(Boolean.parseBoolean(env.getProperty("redis.testOnBorrow"))); config.setTestOnReturn(Boolean.parseBoolean(env.getProperty("redis.testOnReturn"))); JedisPool jedisPool = new JedisPool(config, env.getProperty("redis.host"), Integer.parseInt(env.getProperty("redis.port")), 10000, env.getProperty("redis.password")); ``` 4. 使用连接池 使用连接池从Redis数据库中获取连接,进行相关操作: ``` try (Jedis jedis = jedisPool.getResource()) { // 使用jedis进行相关操作 } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值