首页java › JBOSS连接池合理设置min和max

JBOSS连接池合理设置min和max

连接池设置不合理可能导致的后果

连接池的MIN数和MAX数,看似很简单的两个参数,其实对于应用和数据库的影响,并不是那么的简单。我们先来看看连接数设置不合理可能产生的后果:

  1. 连接池MIN设置过小,应用业务量突增,或者启动时可能产生连接风暴
  2. 连接池MIN值设置过大,会造成资源的浪费,主要包括数据库和应用内存,连接数的浪费,同时连接池MIN值设置过大,也会导致连接被频繁的创建和销毁。这是由连接池的工作机制决定的。
  3. 连接池MAX值设置过大。在极端情况下,当应用发生异常时,会导致连接数被撑到MAX值,有可能导致数据库连接数被耗尽,从而导致正常的业务受到影响。当连接数被撑到MAX值,在获取连接超时的时候,应用的线程池也有可能受到影响,这是一系列的连锁反应。

以上是连接池MIN值和MAX值设置最主要的3点影响。其中,影响最大的并且最难配置的是第2点,即连接数的MIN值设置。

设置连接池的min-pool-size

一般来说,我们可以按照业务高峰时期的压力来估算连接数。比如,在高峰时期,每秒有5000个并发请求,每个请求的处理时间为2ms,则每秒总共需要5000*2ms=10s的连接处理时间。因此,连接数的MIN值我们可以设置为10个(适当上浮1-2个),这样就能基本上解决连接风暴的问题了。当然在业务低峰时期,10个连接数的设置可能偏大了点,所以这里对于连接数的MIN值设置也做了一个权衡,保守起见,我们需要以高峰时需要的正常连接数来设置MIN值,以避免连接风暴的发生。因为这样做是最保险的,当然,这带了一些额外的代价,会牺牲掉部分的数据库和应用的资源。

有时候,我们对于业务的估计可能并不准备,如业务刚上线,对于连接数不能很好的评估,这个时候我们可以对连接池的MIN值进行调优,共有两种方式,如下:

通过ORACLE监听日志对min-pool-size调优

对于ORACLE数据库,我们可以使用数据库的监听日志来进行调优,即通过listener.log(数据库监听日志)进行调优。收集以下几个信息:

1. 根据监听日志,我们可以得到某个应用集群A在2小时内创建的连接总数,假设统计一共为N个。
2. 假设A集群在2小时内的连接数维持在一个值:M。(后面会对这个M进行说明)
3. A集群有S台应用服务器,假设应用服务器负载均衡。

我们知道,连接池IDLE清理是15分钟执行一次的,每次清理空闲时间超过30分钟的连接。所以,2小时内,每台应用平均创建的连接数为:N/4S

假设:
1. M=min连接数,则我们的应用可以下调的MIN连接数为N/4S个,即设置为M-N/4S。(由连接池的原理可以知道,这些新创建的连接完全都是空闲的连接,只是由于配置了MIN值较大而产生的,实际上这些连接一直处于空闲状态)
2.假设M值>min连接数,则需要将min值设置为M。
3.假设M<min,这不可能发生。

之前对于某核心系统做的一次调优,上线后效果很不错,参考 一个生产库的JBOSS连接池调整优化及分析

通过监控JBOSS连接池对min-pool-size的调优

连接池默认参数及获取连接池中相关的统计信息一节中,我们提到了连接池中有一些方法可以获取连接数的信息,其中有三个方法:

//获取连接数,内部执行:return created - destroyed;即所有创建的连接数-所有销毁的连接数
   public int getConnectionCount()
   {
      return connectionCounter.getCount();
   }

//创建连接的总数
   public int getConnectionCreatedCount()
   {
      return connectionCounter.getCreatedCount();
   }
	 //连接销毁总数
   public int getConnectionDestroyedCount()
   {
      return connectionCounter.getDestroyedCount();
   }

通过监控这三个参数我们即可进行连接数的调优,具体的调优方式和方法1一致,只是我们获取创建的连接数,通过监控连接池中的状态获取。如下图所示,我们监控了10:00-12:00数据库的连接数:

 

 

通过上面的图可以知道,我们的连接数MIN值设置过大了(上图是对于单台应用的连接池监控)。因为连接池始终保持在MIN值10个,说明连接数过剩,而我们的连接池不停的创建,销毁。由于定时任务是15分钟启动1次的,所以我们在图上可以看到每隔15分钟说有1个连接被销毁。在30分钟平均有2个连接被销毁。根据同样的ORACLE监听日志的调优算法:

我们的连接数可以被设置为M-N/4S,即10-8/4=8个。

这是二种连接池MIN调整的方案。其实原理是完全一样的,只是获取数据的两种方式不同,对于有条件的应用,建议监控JBOSS的连接池进行调优。这样,连接池的一切状态,都会尽在掌握之中,调优也会变的更加简单高效。

设置连接的max-pool-size

其实我们在调整连接池MIN值的时候,已经是按业务的高峰时期进行调整。所以MAX值调整的意义其实并不大,我们只要将MAX值设置在一个安全的阀值即可。保证不超过数据库的连接数,同时又保证在业务偶尔分布不均匀时,应用也能够获取连接,防止连接池取不到的情况。

我们经常会看到应用程序报错:“No ManagedConnections available within configured blocking timeout xx [ms]”,这其实是由于连接池达到最大值了,没有可用的连接的时候产生的。(参考:JBOSS连接池4-从连接池中获取连接及返还连接)。产生这个问题,最根本的原因往往并不是连接数不够用,我们应该首先看看数据库的响应和应用DAO的响应时间。有时候因为SQL走不上索引,或者数据库响应较慢,会增加业务占用连接的时间(即处理时间),这种情况下,加大MAX连接数可以从一定程序上缓解问题,但是不能解决根本的问题。

blocking-timeout-millis的设置

另外一点建议是,将blocking-timeout-millis参数设置的尽量小一点,这个参数是应用getconnection时的超时时间,只在连接数达到MAX值时才会起作用,因为连接数没到达MAX值,这个获取连接是一个很快的操作,内部仅仅是执行一个获取信号量的操作。为了尽量的减小在获取不到连接而等待超时对应用线程池的阻塞,我们需要将blocking-timeout-millis参数设置为一个较小的值即可,这样,当连接池中无可用的连接时,由于超时时间减小了,可以避免由于线程池共享造成对其它正常业务的影响,特别是一个应用连接多个数据源时,这个值的设置尤其重要。

总结

实际我们对于连接池的调优,需要从连接池的原理入手,只有理解了原理,才能够更好的将连接池控制在我们所想要的一个状态。因为连接池的不合理设置所产生的问题,我们在上面吃的亏很多。就因为一个小小的连接池出了问题,现在看来实在有点得不偿失。

真实的场景中,特别是基于数据库的水平拆分,或者读写分离的场景中,当一个应用集群需要连接多个数据源时,我们尤其需要考虑连接池的这几个参数:prepared-statement-cache-size,min-pool-size, max-pool-size, blocking-timeout-millis。这几参数设置的利害关系,需要仔细的考虑。另外,我们还需要重点考虑2个点:

  1. 对于物理库-逻辑库中,数据源共享和不共享的取舍。
  2. prepared-statement-cache-size,min-pool-size值的设置,数据源个数,fetchsize的设置 直接影响到JVM内存的使用。

发表评论

注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>