经常使用池化技术

 

 版权声明:本文为博主原创文章,未经博主容许不得转载。 https://blog.csdn.net/itest_2016/article/details/78084202

在系统开发过程当中,咱们常常会用到池化技术来减小系统消耗,提高系统性能。对象池经过复用对象来减小建立对象、垃圾回收的开销。链接池(数据库链接池、Redis链接池、HTTP链接池)经过复用TCP链接来减小建立和释放链接的时间。线程池经过复用线程提高性能。简单来讲,池化技术就是经过复用来提高性能。html

 

1、数据库链接池数据库

  数据库链接池基本的思想是在系统初始化的时候,将数据库链接做为对象存储在内存中,当用户须要访问数据库时,并不是创建一个新的链接,而是从链接池中取出一个已创建的空闲链接对象。使用完毕后,用户也并不是将链接关闭,而是将链接放回链接池中,以供下一个请求访问使用。而链接的创建、断开都由链接池自身来管理。同时,还能够经过设置链接池的参数来控制链接池中的初始链接数、链接的上下限数以及每一个链接的最大使用次数、最大空闲时间等等,也能够经过其自身的管理机制来监视数据库链接的数量、使用状况等。tomcat

 

  DBCP是一个依赖 commons-pool对象池机制的数据库链接。DBCP能够直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。服务器

 

 DBCP关键配置:多线程

最小链接数: minIdle并发

数据库一直保持的数据库链接数,若是应用程序对数据库链接的使用量不大,将有大量的数据库资源被浪费。性能

 

最大空闲链接数:maxIdleui

数据库容许的最大空闲链接数,超过的空闲链接将自动被释放。spa

 

初始化链接数:initialSize.net

链接池启动时建立的初始化数据库链接数量。

 

最大链接数:maxTotal

链接池能申请的最大链接数,若是数据库链接请求超过此数,后面的数据库链接请求被加入到等待队列中。

 

最大等待时间:maxWaitMillis

当没有可用链接时,链接池等待链接被归还的最大时间,超过期间则抛出异常,可设置参数为0或者负数使得无限等待(根据不一样链接池配置)。但设置超时时间太长容易形成大量的TIMED_WAIT和线程阻塞,形成滚雪球的效果,一旦出现问题很难恢复。

 

2、HttpClient链接池

  HttpClient 咱们常常用来进行HTTP服务访问。咱们的项目中有一个获取任务执行状态的功能使用HttpClient,一秒钟请求一次,常常出现Connection reset异常。通过分析发现,因为咱们的httpClient每次请求都新建一个链接,建立链接的频率比链接关闭的频率大,致使了系统中产生了大量处于TIME_CLOSED状态的链接。这个时候使用链接池复用链接就解决了这个问题。    

HttpClient链接池实现源码

response = requestExecutor.execute(request, managedConn, context);

if(reuseStrategy.keepAlive(response, context)){

    final long duration=keepAliveStrategy.getKeepAliveDuration(response, context);

    connHolder.setValidFor(duration, TimeUnit,.MILLISENCONDS);

    connHolder.markReuseable();

}else{

    connHolder.markNonReuseable();

}

 

 

从上述源码能够看出,HttpClient请求的步骤为:

一、发生请求并接收响应

二、判断响应是否长链接(长链接才可复用),非长链接标记为不可复用

三、获取长链接超时周期(若是没有设置,则永不过时)

四、设置过时周期,并标记为可复用

 

HttpClient经过PoolingHttpClientConnectionManager类来管理链接池,能够同时为不少线程提供http链接请求。当请求一个新的链接时,若是链接池有可用的持久链接,链接管理器就会使用其中的一个,而不是再建立一个新的链接。

PoolingHttpClientConnectionManager维护的链接数在每一个路由基础和总数上都有限制。默认,每一个路由基础上的链接不超过2个,总链接数不能超过20。在实际应用中,这个限制可能会过小了,尤为是当服务器也使用Http协议时

 

下面的例子演示了若是调整链接池的参数:

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// 将链接池最大链接数设置到200

cm.setMaxTotal(200);

// 将每一个路由最大链接数设置为20

cm.setDefaultMaxPerRoute(20);

HttpHost localhost = new HttpHost("www.xxx.com", 80);

  //将目标主机的最大链接数增长到50

    cm.setMaxPerRoute(new HttpRoute(localhost), 50);

 

CloseableHttpClient httpClient = HttpClients.custom()

.setConnectionManager(cm)

.build();

 

3、Tomcat线程池

 

tomcat线程池有以下参数:

acceptCount: 等待队列大小 ,当Tomcat没有可用空闲线程处理链接请求时,新来的链接请求将放入等待队列中。当队列超过acceptCount时,后续的链接请求就会被拒绝。

 

maxThreads:线程池最大线程数,tomcat能建立来处理请求的最大线程数,当线程池空闲一段时间后会释放到只保留minSpareThreads个线程。

 

maxSpareThreads:最大空闲线程数,在最大空闲时间内活跃过,但如今处于空闲,若空闲时间大于最大空闲时间,则回收,小于则继续存活,等待被调度。

 

minSpareTHreads:最小空闲线程数,不管如何都会存活的最小线程数。

 

maxIdleTime: 最大空闲时间,超过这个空闲时间,且线程数大于最小空闲数的,都会被回收。   

  

Tomcat线程池在工做的时候,实际状况是:一开始就建立最小空闲数的线程在池里,20个,当同一时间请求数量大于最小空闲数20,好比来了50个并发请求,那么线程池还须要建立30个线程来处理请求。这时候当请求都处理完了,持续来的请求低于50个的时候,那么当时间过了60秒,并发数仍是没有达到50,那么从第50个线程开始,线程池将按照,空闲时间达到60s的,开始逐个回收,49个,48个,47个,如此回收。若是并发请求小于20个,那么线程池会回收至20个的时候,中止回收,这就是最小空闲数的做用,即便一个请求都没有,那么线程池也得保证随时都有20个。所谓空闲回收是指:一个线程在60s的时间内,一直处于等待。那么就能够断定该线程是空闲。若是这个空闲线程是在最小空闲数以上,则会被回收。当请求并发高于500最大空闲数的时候,线程池是会继续建立线程的,来知足特大突发性并发。当并发请求数降下以后,线程池中有空闲,那么,不管线程空闲时间是否达到60s,线程池都会进行回收至500。500之内的线程也会根据空闲时间是否大于60s来判断是否须要进行回收。

 

4、总结

   经过数据库链接池、HttpClient链接池、Tomcat线程池这三个最经常使用的案例不难看出

这几个池化技术共同点实现的原理都是相似的,经过对链接或线程的复用,并对复用的数量、时间等进行控制,从而使系统的性能和资源消耗达到最优的状态。实际项目中,咱们能够考虑使用池化技术来解决程序性能的瓶颈。

相关文章
相关标签/搜索