Thrift RPC實戰(四) common-pool2鏈接池

咱們在服務器開發的過程當中,每每會有一些對象,它的建立和初始化須要的時間比較長,好比數據庫鏈接,網絡IO,大數據對象等。在大量使用這些對象時,若是不採用一些技術優化,就會形成一些不可忽略的性能影響。一種辦法就是使用對象池,每次建立的對象並不實際銷燬,而是緩存在對象池中,下次使用的時候,不用再從新建立,直接從對象池的緩存中取便可。Thrift自己沒有提供鏈接池,咱們能夠用Apache Commons Pool來實現一個,它對對象池化操做進行了很好的封裝,咱們只須要根據本身的業務需求重寫或實現部分接口便可,使用它能夠快速的建立一個方便,簡單,強大對象鏈接池管理類。redis

一,common-pool2簡介

Common-pool2中的代碼不是太多,有幾個種要的接口和實現類,common-pool2使用的是面向接口的編程,它爲咱們提供的是一個抽象的對象池管理方式,因此根據咱們業務的不一樣,咱們須要重寫或實現一些方法和接口數據庫

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.5.0</version>
</dependency>

1,GenericObjectPool

這個是對象池實現的核心類,它實現了對對象池的管理,是一個基本的對象池實現,通常狀況下,咱們能夠直接使用。在使用這個類的時候,咱們須要傳入兩個重要的參數:GenericObjectPoolConfig類和PooledObjectFactory接口的實現,一會咱們再詳細說這兩個。apache

在GenericObjectPool中,有兩個咱們會用到的方法:編程

public T borrowObject throws Exception 從對象池中獲取一個對象緩存

public void returnObject(T obj) 對象使用完以後,歸還到對象池,安全

其它還有一些方法,好比關閉對象池,銷燬對象池,獲取對象池中空閒的對象個數等,能夠自行查看API。服務器

2,PooledObjectFactory接口

這個接口是咱們要實現的,它對要實現對象池化的對象作了一些管理。這個工廠接口就是爲了讓咱們根據本身的業務建立和管理要對象池化的對象。網絡

T makeObject() throws Exception;

這個方法是用來建立一個對象,當在GenericObjectPool類中調用borrowObject方法時,若是當前對象池中沒有空閒的對象,GenericObjectPool會調用這個方法,建立一個對象,並把這個對象封裝到PooledObject類中,並交給對象池管理。socket

void destroyObject(T obj) throws Exception;

銷燬對象,當對象池檢測到某個對象的空閒時間(idle)超時,或使用完對象歸還到對象池以前被檢測到對象已經無效時,就會調用這個方法銷燬對象。對象的銷燬通常和業務相關,但必須明確的是,當調用這個方法以後,對象的生命週期必須結果。若是是對象是線程,線程必須已結束,若是是socket,socket必須已close,若是是文件操做,文件數據必須已flush,且文件正常關閉。性能

boolean validateObject(T obj);

檢測一個對象是否有效。在對象池中的對象必須是有效的,這個有效的概念是,從對象池中拿出的對象是可用的。好比,若是是socket,那麼必須保證socket是鏈接可用的。在從對象池獲取對象或歸還對象到對象池時,會調用這個方法,判斷對象是否有效,若是無效就會銷燬。

void activateObject(T obj) throws Exception;

激活一個對象或者說啓動對象的某些操做。好比,若是對象是socket,若是socket沒有鏈接,或意外斷開了,能夠在這裏啓動socket的鏈接。它會在檢測空閒對象的時候,若是設置了測試空閒對象是否能夠用,就會調用這個方法,在borrowObject的時候也會調用。另外,若是對象是一個包含參數的對象,能夠在這裏進行初始化。讓使用者感受這是一個新建立的對象同樣。

void passivateObject(T obj) throws Exception;

鈍化一個對象。在向對象池歸還一個對象是會調用這個方法。這裏能夠對對象作一些清理操做。好比清理掉過時的數據,下次得到對象時,不受舊數據的影響。

通常來講activateObject和passivateObject是成對出現的。前者是在對象從對象池取出時作一些操做,後者是在對象歸還到對象池作一些操做,能夠根據本身的業務須要進行取捨。

3,帶Key的對象池GenericKeyedObjectPool

這種對象池和前面的GenericObjectPool對象池操做是同樣的,不一樣的是對應的每一個方法帶一個key參數。你能夠把這個GenericKeyedObjectPool的對象池看做是一個map的GenericObjectPool,每一個key對應一個GenericObjectPool。它用於區別不一樣類型的對象。好比數據庫鏈接,有可能會鏈接到不一樣地址的數據庫上面。就能夠用這個區分。

4,參數配置類GenericObjectPoolConfig

這個類容許使用者對對象池的一些參數進行調整,根據須要定製對象池。下面說逐一說一下每一個參數的含義。

lifo:對象池存儲空閒對象是使用的LinkedBlockingDeque,它本質上是一個支持FIFO和FILO的雙向的隊列,common-pool2中的LinkedBlockingDeque不是Java原生的隊列,而有common-pool2從新寫的一個雙向隊列。若是爲true,表示使用FIFO獲取對象。默認值是true.建議使用默認值。

fairness:common-pool2實現的LinkedBlockingDeque雙向阻塞隊列使用的是Lock鎖。這個參數就是表示在實例化一個LinkedBlockingDeque時,是否使用lock的公平鎖。默認值是false,建議使用默認值。

maxWaitMillis:當沒有空閒鏈接時,獲取一個對象的最大等待時間。若是這個值小於0,則永不超時,一直等待,直到有空閒對象到來。若是大於0,則等待maxWaitMillis長時間,若是沒有空閒對象,將拋出NoSuchElementException異常。默認值是-1;能夠根據須要本身調整,單位是毫秒。

minEvictableIdleTimeMillis:對象最小的空閒時間。若是爲小於等於0,最Long的最大值,若是大於0,當空閒的時間大於這個值時,執行移除這個對象操做。默認值是1000L * 60L * 30L;即30分鐘。這個參數是強制性的,只要空閒時間超過這個值,就會移除。

softMinEvictableIdleTimeMillis:對象最小的空間時間,若是小於等於0,取Long的最大值,若是大於0,當對象的空閒時間超過這個值,而且當前空閒對象的數量大於最小空閒數量(minIdle)時,執行移除操做。這個和上面的minEvictableIdleTimeMillis的區別是,它會保留最小的空閒對象數量。而上面的不會,是強制性移除的。默認值是-1;

numTestsPerEvictionRun:檢測空閒對象線程每次檢測的空閒對象的數量。默認值是3;若是這個值小於0,則每次檢測的空閒對象數量等於當前空閒對象數量除以這個值的絕對值,並對結果向上取整。

testOnCreate:在建立對象時檢測對象是否有效,true是,默認值是false。

testOnBorrow:在從對象池獲取對象時是否檢測對象有效,true是;默認值是false。

testOnReturn:在向對象池中歸還對象時是否檢測對象有效,true是,默認值是false。

testWhileIdle:在檢測空閒對象線程檢測到對象不須要移除時,是否檢測對象的有效性。true是,默認值是false。

timeBetweenEvictionRunsMillis:空閒對象檢測線程的執行週期,即多長時候執行一次空閒對象檢測。單位是毫秒數。若是小於等於0,則不執行檢測線程。默認值是-1;

blockWhenExhausted:當對象池沒有空閒對象時,新的獲取對象的請求是否阻塞。true阻塞。默認值是true;

maxTotal:對象池中管理的最多對象個數。默認值是8。

maxIdle:對象池中最大的空閒對象個數。默認值是8。

minIdle:對象池中最小的空閒對象個數。默認值是0。

以上就是common-pool2對象池的配置參數,使用的時候能夠根據本身的須要進行調整。

5,common-pool2的應用

使用common-pool2的對象池技術的一個完美例子就是redis的Java客戶端JedisPool。你們能夠下載Jedis的包,查看源碼進行學習。下一篇文章我使用common-pool2實現的一個thrift客戶端調用的鏈接池實現。

綜上所述,使用common-pool2能夠快速的建立一個安全,強大,簡單的對象池管理類。它的開源性使它的功能獲得了衆多項目的檢測,是很是安全的。在咱們的業務中,若是有須要使用對象池化的操做,可使用common-pool2快速實現。

相關文章
相關標籤/搜索