SockIOPool

1. SockIOPool – SockIO池化管理,爲上層提供的接口是實例化函數[主要是指定memcached服務器地址,各個
機器的權重];根據key&hashCode獲取SockIO-網絡鏈接句柄;根據服務器地址獲取SockIO;關閉池。上層在獲取
到SockIO後能夠進行讀寫操做,在正常使用完SockIO後將其歸還給池,若是在使用過程當中出現問題則將這個網絡
鏈接關閉,同時還暴露了SocketChannel提供了進行NIO編程的接口。
SockIOPool有在static可見範圍維護一個String池名到SockIOPool的映射。
SockIO進入availPool或者busyPool都會把進入的時間寫入,做爲空閒時間或者使用時間的參考
------------------
2. SockIOPool屬性
    boolean initialized = false – 初始化是否完成的標誌,只有初始化完成後上層才能正常使用池
    int initConn = 10 – 初始化時對每一個服務器創建的鏈接數目
    int minConn = 5 – 每一個服務器創建最小的鏈接數,當自查線程發現與某個服務器創建鏈接數目小於這個數目時
    會彌補剩下的鏈接
    int maxConn = 100 -每一個服務器創建最大的鏈接數,當自查線程發現與某個服務器創建鏈接數目大於這個數目
    時就會逐個檢查這些鏈接的空閒時間是否大於maxConn,若是大於會關閉這些鏈接,直到鏈接數等於maxConn
    long maxIdle = 1000 * 60 * 5 – 最大空閒時間
    long maxBusyTime = 1000 * 30 – 最長租用時間,其使用主要有兩點,一是自查線程會檢查正在被租用的鏈接,
    若是發現已經被租用的時間超過這個值得,會將其從被租用的記錄裏剔除,並關閉這個鏈接;另外一個應用是
    上層進行MUTIL操做時,讀取全部的數據的時間不能超過這個時間。
    long maintSleep = 1000 * 30 – 自查線程週期進行工做,其每次休眠時間
    int socketTO = 1000 * 3 – Socket阻塞讀取數據的超時時間
    int socketConnectTO = 1000 * 3 - Socket阻塞創建鏈接的等待時間
    boolean aliveCheck = false -根據key&hashCode獲取SockIO時,經過hash bucket獲得SockIO後,若是這個值
    是true會檢查Socket是否已經鏈接,若是鏈接創建正常還會想服務器發送「version\r\n」的指令,並讀取數據,這
    個過程沒有出錯纔會返回SockIO給上層用,不然返回NULL。因此通常設置爲false。
    boolean nagle = false – Socket的參數,若是是true在寫數據時不緩衝,當即發送出去
    int hashingAlg = NATIVE_HASH – 池的hash bucket方式,主要是分爲簡單的hashCode取hash bucket數目的模
    和一致性哈希,前者在擴容時會形成命中率很大程度的降低,後者的好處是擴容時很大程度減小了緩存的從新
    分佈
    String[] servers – memcached服務器地址配置
    Integer[] weights – memcached服務器權重配置
    List<String> buckets - hash bucket,一個服務器地址,其權重是N,則往這個bucket中添加N個服務器地址
    TreeMap<Long, String> consistentBuckets – 一致性哈希表:一個服務器地址,其權重是N,則迭代0 - N-1,取
    字符串服務器地址+i的MD5值,將這個MD5值分紅4段,每段轉換成Long值,將這個Long值到服務器地址放入
    到一致性哈希表中
    Map<String, Date> hostDead – 用來記錄本地和哪一個服務器地址創建鏈接失敗的最近時間的MAP
    Map<String, Long> hostDeadDur – 若是hostDead包含服務器地址,說明上次創建鏈接失敗了,那麼會到
    hostDeadDur裏取這個服務器不必嘗試鏈接時間間隔的值,若是上次失敗時間+不必嘗試鏈接時間間隔則
    不會發起鏈接。在每次鏈接服務器失敗後,會替換hostDead裏最近時間,同時替換hostDeadDur的時間間隔
   值,這個值初始是1000ms,每失敗一次翻倍一次。
    Map<String, Map<SockIO, Long>> availPool – 當前可用的鏈接記錄
    Map<String, Map<SockIO, Long>> busyPool – 當前工做的鏈接記錄
    Map<SockIO, Integer> deadPool – 用來保持應該關閉鏈接的SockIO,自查線程會將裏面的全部的SockIO的鏈接
   關閉
    boolean failover/failback
------------------
3. 池初始化
在初始化階段主要是完成一些值的初始化,再就是根據hashingAlg來設置hash bucket,若是是
CONSISTENT_HASH則使用上面提到的一致性HASH算法創建一致性哈希表,若是不是則使用上面提到的創建
hash bucket,接下來根據initConn和全部服務器地址建立數目爲initConn的鏈接數目。若是maintSleep大於0則
啓動整個鏈接池的自查線程。其中建立鏈接的邏輯以下:若是hostDead和hostDeadDur都持有一個服務器地址
的時候,會看最近失敗時間+不必鏈接時間間隔是否大於當前時間,大於的話直接放棄建立鏈接過程退出,
小於則發起鏈接,發起鏈接建立有三種狀況,一種是在時間期限內建立成功,則清空其可能在hostDead和
hostDeadDur的記錄,再將這個鏈接放入到availPool記錄裏面;一種是鏈接沒有建立成功則將SockIO放入到
deadPool裏給自查線程關閉鏈接和釋放資源;最後一種是因爲網絡異常或者超時異常,第二種和第三種狀況
發生則須要往hostDead和hostDeadDur裏添加這個服務器地址的相關記錄,同時將availPool裏的這個服務器
地址的記錄清除。
------------------
4. 租還SockIOPool
a. key & hashCode - 租
1. 先根據key & hashCode到hash bucket裏找到其應該鏈接的服務器地址:若是有hashCode則直接使用
hashCode,沒有則根據hashingAlg取hash值。若是是一致性哈希算法則到consistentBuckets裏找計算出的大hash
值的點,沒找到則取第一個;若是是其餘的則hash bucket取模。
2. 到availPool里根據服務器地址找到可用的鏈接列表,迭代這個列表,若是有可用的則從availPool取出,
並加入到busyPool,若是不可用則加入到deadPool給自查線程關閉鏈接。通過上面的過程尚未獲得鏈接則調用
上面提到的建立鏈接的邏輯,若是建立成功加入到busyPool。
3. 在獲得一個鏈接SockIO後,再進行一些檢查,若是鏈接不可用則加入到deadPool,可用若是aliveCheck
爲true則會進行上面提到的自檢操做,若是自檢發生錯誤則從busyPool中移除並關閉鏈接。若是在2沒有獲得連
接,而且failover爲false則直接返回再也不嘗試鏈接到其餘機器了;不然會組裝一些新的key到hash bucket裏去找剩
下的服務器地址按2創建鏈接。
b. host - 租
到availPool里根據服務器地址找到可用的鏈接列表,迭代這個列表,若是有可用的則從availPool取出,
並加入到busyPool,若是不可用則加入到deadPool給自查線程關閉鏈接。通過上面的過程尚未獲得鏈接則調用
上面提到的建立鏈接的邏輯,若是建立成功加入到busyPool。
c. 還
將此鏈接SockIO從busyPool的記錄中移除,若是鏈接可用則將鏈接加入到availPool的記錄裏面。
------------------
5. 自查線程
自查線程主要提供兩個邏輯,啓動和關閉,啓動時週期性調用池的自查邏輯,關閉則經過一個是否中止標誌來的
設置來標記中止,在中斷可能正在休眠的自查線程。
池的自查邏輯主要是:
a. 到availPool檢查各個服務器目前可用鏈接數目的個數,若是小於minConn則建立鏈接來彌補差額,建立的新
的鏈接加入到availPool中。
b. 再到availPool檢查各個服務器目前可用鏈接數目的個數,若是大於maxConn會逐個檢查這些鏈接的空閒時間
是否大於maxConn,若是大於會關閉這些鏈接,直到鏈接數等於maxConn。空閒時間的計算就是當前時間和這個
鏈接進入availPool時間的差值。
c. 到busyPool檢查,發現某個鏈接已經被租用的時間超過這個值得,會將其從被租用的記錄裏剔除,並將其加入
到deadPool中。
d. 迭代deadPool中全部的鏈接,關閉這些鏈接。
------------------
6. 關閉過程主要是先中止自查線程,直到自查線程結束運行,再迭代availPool和busyPool將裏面的網絡鏈接
SockIO,關閉SockIO主要是關閉輸入輸出流,關閉Socket。算法

相關文章
相關標籤/搜索