經常使用池化技術

 

 版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 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線程池這三個最經常使用的案例不難看出

這幾個池化技術共同點實現的原理都是相似的,經過對鏈接或線程的複用,並對複用的數量、時間等進行控制,從而使系統的性能和資源消耗達到最優的狀態。實際項目中,咱們能夠考慮使用池化技術來解決程序性能的瓶頸。

相關文章
相關標籤/搜索