王宇杰,楊文賓
在數據庫的訪問中,采用連接池技術在并發性能的處理上以及用戶時延的等待上都有很大優勢。但通用的連接池具有效率低、缺乏監控的缺點。本文在連接池的設計中,應用排隊論的理論,建立了一個訪問服務模型,用以優化連接池的服務質量。
文中設計連接池模型具有一定的通用性,可以用在對各種數據庫的連接應用中。
連接池在總體上包括四個部分:連接池、管理器、監視器和配置文件。如圖1所示。
圖1 連接池模塊總體結構
連接池是存放具體連接實例的地方,需要注意的是,每個連接池對應著一種連接方式,比如對同一個數據庫,不同的數據庫用戶所建立的連接就要放在不同的連接池中(因為連接參數不一樣)。一個連接池中可以存放若干個連接實例。每個實例對應一個編號和一些使用屬性,如已經被使用的次數,被創建的時間,上一次被使用的時間等。通過這些信息,就可以對這個實例進行管理(分配、回收和銷毀等)以及由此獲得系統的某些性能參數。每個連接池也設置一些參數,或者用于記錄整個連接池的被使用情況,或者用來控制連接池的某些行為。連接池可以被設計成一個類,主要存放有一些有關連接池狀態的信息,也可以自主地對存儲在其內的連接實例進行管理(生成、銷毀和維護等)。
管理器是對連接池進行管理的部分。一個管理器可以管理若干個連接池,負責每個連接池的生成和銷毀。管理器從配置文件中獲得靜態的配置信息,如:可以管理的連接池的列表,每個連接池的連接信息,每個連接池的最大連接數或總體的最大連接數,建立連接時最大的等待時間等。用這些信息生成各個連接池,在系統停止時管理器還負責銷毀各個連接池(回收資源)。
由于各個連接池都由管理器統一管理,所以管理器也為應用程序提供連接池的使用接口,所有應用程序都通過管理器的接口來獲得合適的連接實例以及釋放(連接池回收)一個連接實例。
監視器是一個后臺運行的守候進程(或線程),本質上是一種對連接池進行優化的計算程序。它以一定頻率掃描連接池的被訪問頻率和連接操作反應速度的統計信息,并以此為依據,計算最優的連接池參數,供連接池使用。訪問的統計信息反應了用戶的訪問情況,連接操作的統計信息訪問了服務器的當前狀態(負荷、性能等),再通過一定的排隊論模型計算,就可以大致確定連接池適應當前狀況的最優狀態,從而動態的對連接池進行調整,提高服務質量(QoS)。
監視器是與連接池相對應的,每個連接池實例對應一個監視器實例,這個監視器實例在與之對應的連接池實例被創建的時候啟動,之后就不停地監視和調整連接池實例的狀態。因為應用程序對連接池的訪問就是個排隊論的問題,所以監視器的算法以排隊論為理論基礎,通過建立一個合適的排隊模型進行優化計算。
配置文件是存放連接池的靜態參數的地方,比如可管理的連接池名稱列表,每個連接池建立連接所用的用戶名,密碼,服務器地址,數據庫名稱,連接驅動程序名稱等。這些數據都是關于連接池全局的數據,都是在管理器每次啟動時,一次性裝入,此后便不再對連接池產生任何作用。
連接池管理器有兩個主要作用:一是按照配置文件中的配置信息建立和銷毀連接池。一是按照應用程序的要求,向相應的連接池實例請求可用的連接實例或回收一個連接實例,即要實現取得和回收連接實例的接口。
連接池的設計主要有3點考慮:
1.管理器在設計上需要注意的就是它只能生成一個實例,換句話說,第一個管理器實例生成后,要能禁止第二個管理器實例的生成,保證所有的連接池統一管理。
2.應用程序在請求獲釋放連接時,僅僅指出連接池的名稱,即可通過管理器提供的接口獲得或釋放一個連接實例。管理器內部依據這個名字,向其所管理的某個連接池申請連接實例并返回給應用程序,或者回收這個連接實例。這個過程對應用程序透明。
3.管理器在實現這個接口時,還要注意多個進程(線程)使用接口時所造成的同步問題;一方面,我們希望提高程序的并行程度,即在同一時間內允許有多個應用訪問管理器,以此來提高系統的運行效率;另一方面,還要嚴格注意到并行過程中不適當的代碼可能造成的混亂。所以,對管理器的設計我們力求避免實現繁瑣而又不甚必要的功能。
2.2.1 連接池的主要功能
(1)要能生成、維護和銷毀所管理的連接實例;
(2)要能迅速地對管理的連接實例進行檢索,返回給應用程序(通過管理器),或從管理器回收一個連接實例;
(3)要維護各個連接實例的相關信息,以便于實現對連接實例和連接池的維護;
(4)要能及時地為監視器提供有用的統計信息以供監視器進行優化計算。
2.2.2 連接池中的數據組織
在實際設計中,一個連接池主要包括如下一些重要數據組織:
(1)鏈表cons,我們把空閑的連接實例放入這個鏈表中,因為對連接實例的操作主要是取得(不需檢索)、加入和刪除等修改性操作,采用鏈表結構最為適合。
(2)哈希表infos,我們把連接實例的相關信息放入一個哈希表中,每個連接實例的相關信息包括實例創建時間,實例被使用的次數,實例上次被調用的時間。因為對連接實例相關信息的查詢操作比較頻繁,不同于連接實例本身,所以,把相關信息和連接實例本身分開存儲;哈希表比較適合于查詢,所以就把連接實例信息放在哈希表中。
(3)還設有兩個變量專門用于統計系統的被訪頻率和系統當前的反應速度uCount和yCount,連接池會根據實際情況不斷地把一些信息計入這兩個變量,監視器也會不斷地訪問這兩個變量,以進行優化計算。
(4)其他比較重要的參數就是連接池內最大的連接實例數n,連接池內等待連接的請求隊列的最大長度(m-n),這兩個參數對連接池的性能有較大的影響,監視器會根據計算結果不斷調整n和m的值,以期連接池的性能最優。
此外還有一些不太重要的參數,如連接實例的最大生存時間,最大使用次數,最長等待時間,已經生成的所有連接數(包括正在被使用和空閑狀態中的連接實例)等等。
2.2.3 連接池向外提供的接口
連接池主要向外提供兩個接口:獲取連接getConnection(),即是從連接池取得一個可用的連接實例;釋放連接freeConnection(),即是將一個用完的連接實例放回連接池。這兩個接口都需要調用者提供一個連接池名稱作為參數。
2.2.4 連接池的運行流程
考慮到一個連接實例在多次使用之后,或在經過較長一段時間之后會逐漸的變得不穩定(由于底層的原因),所以,在回收連接實例時,連接池要檢查連接實例的生成時間和使用次數,當超過相應的標準時,就把這個連接實例銷毀,同時刪除對應的使用記錄。
一個連接池的運行流程分析如下。
(1)管理器應應用程序的請求,調用連接池的獲取連接接口getConnection()。連接池首先把這個請求的有關信息記錄到yCount中去,然后,看空閑連接鏈表cons中有沒有可用的連接實例,如果有,到哈希表infos中修改這個連接實例的相關信息,并返回這個連接實例給管理器;如果空閑鏈表已經空了,則查看所有連接數是否達到最大值n,如果沒有達到,則生成一個新的連接實例,把相關信息計入哈希表infos,并返回這個新的連接實例給管理器;如果已經達到最大值,則看等待隊列有沒有排滿,若沒滿,則把這個請求放入等待隊列,若已滿,返回出錯信息給管理器,報告沒有取道連接。放入等待隊列的請求也有一個最大的等待時間,如果在這個時間內,沒有獲得可用連接,則也要返回出錯信息給管理器。如果我們還要對請求失敗率進行統計的話,在合適的地方,還要對相關信息進行記錄。
(2)管理器應應用程序的請求,調用連接池的釋放連接接口freeConnection()。連接池首先從哈希表infos中取出這個連接實例的相關信息,并把相關信息記錄到uCount中去,然后檢查這個連接實例的生存時間和使用次數是否超過要求,如果已經超過,關閉這個連接,刪除相關信息,所有連接數減1。如果沒有超過,則把這個連接實例放入空閑鏈表cons,相關信息中使用次數加1,然后通知等待隊列,已經有空閑連接實例回收。
(3)連接池實例一旦生成,即啟動一個監視器實例monitor,這個監視器以后臺守護進程或線程的方式運行,經過一段間隔,就查詢連接池中的統計信息yCount和uCount,并進行一次優化計算,并根據計算結果,調整連接池中的m和n值。在銷毀連接池之前,要停止監視器最后銷毀掉。
連接池的運行流程如圖2所示,實際上包括兩個獨立的過程:
(a)應用程序向連接池申請一個連接的過程;
(b)應用程序向連接池釋放一個連接的過程;
圖2 連接池處理流程
2.3.1 監視器算法
監視器的作用就在于,按照一定的指標,通過模型計算,得到合適的連接池參數。優化的目標主要有兩個:一個是盡量提高系統的通過能力,即是要使絕對通過量保持不低于某一個值(與系統能力有關);一個是盡量減小對每個用戶的服務時間,不能讓用戶等待的太久。
這兩個指標在有些時候是矛盾的,假設系統資源已經達到極限,為了提高系統通過率,可以增加每個連接池內的連接數,使更多到達的請求不被馬上拒絕,但這樣肯定會增大整個系統的開銷,使得等待隊列中的請求等待的時間延長。反之,如果想讓每個以獲得連接的用戶花費時間短,就不能在連接池內創建太多的連接,以節省系統資源,從而降低了系統的通過率。
所以,必須分情況采用不同的優化策略,權衡兩個因素,以期達到最佳效果。在平均的請求速度低于平均的響應速度時,說明系統是可以勝任當前任務的,所以應該盡量保證系統通過率,適當地增加連接實例以及加長等待隊列的長度,使一些局部密集到達的請求不至于被馬上拒絕掉。在平均的請求速度高于平均的響應速度時,說明系統是已經不可以勝任當前任務了,一些請求被拒絕是必然的,這時,就應該保證每個用戶的響應時間,在此基礎上,盡量提高系統通過量,所以就要限制連接池內連接實例數目和等待隊列的長度,適當拒絕對某些申請的響應。
從而得到如下的優化算法:
Λ:為單位時間內平均到達的請求數量;
μ:為單位時間內每個連接實例所能處理的請求數;
n:為連接池內所有的連接實例數目;
m:等待隊列長度;
timeout:用戶最大等待時間;
(1)使用當前的λ、μ、m和n值,比較nμ和λ,如果nμ>λ說明系統目前設置基本上能夠勝任當前任務,僅僅需要微調,進入第二步計算。
(2)計算用戶等待時間,如果計算結果已經大于timeout,則適當增加m值重復計算,但m值不要大于2n,如果在某一個時刻,計算結果小于timeout了,計算完成,本輪計算結束。當增加到m=2n時,若還沒有使計算結果小于timeout,此時m值的增加對計算結果的影響已經很小,說明不能靠調整m值來縮短響應時間了,轉入第四步。如果計算結果小于timeout,轉入第三步。
(3)減小m值,值到計算的等待時間剛好小于timeout,本輪計算完成。如果一直到m=n尚不能使等待時間剛好小于timeout,轉入第四步。
(4)n值減1,本輪計算完成,等待下一輪計算。
(5)使用當前的λ、μ、m和n值,比較nμ和λ,如果nμ<λ說明系統目前設置不能夠勝任當前任務,需要大的調整,轉入第六步。
(6)檢查以前記錄的μ和n值,其乘積與當前值乘積進行比較,如果當前值較大且n+1值有效,說明系統尚有空余利用空間,記錄下當前μ和n值存儲起來,n值加1,本輪計算完成,等待下一輪計算。如果當前值較小,轉入第七步計算。如果n+1值無效,同樣轉入第七步計算進行微調。
(7)此時系統資源的利用到達極限,且還不能滿足當前任務,使一部分的用戶請求被拒絕已經無法避免,所能做的就是保證連接用戶的等待時間在規定的等待時間內,同時,盡可能提高系統通過率。計算方法是計算等待時間是否小于規定時間,如果是,逐步增加m值,直到一個臨界值(并且m<2n),如果不是,逐步減小m值,直到一個臨界值;如果一直到m=n尚不能滿足要求,說明通過調整等待隊列長度不能完成用戶等待時間的調整,從而轉入第八步計算。
(8)做一個標記,表示當前n值無效,n值減1,進入下一輪計算。
優化算法的流程可參考圖3,其中的具體算法參考排隊論理論。
圖3 監視器算法流程圖
可以看出,因為n值的調整會對系統有較大的影響,所以一般n值變化后要等到下一輪實測結果出來再做進一步決定(此時的實測結果可能會較現狀有較大的變化),調整周期要長;而m值的調整對系統影響較小,可以用過迭代計算在一輪內算得出,調整周期要短的多。調整n值時伴隨著連接實例的建立和銷毀,是個很費資源的工作,但m值的調整則沒有這么大的影響,而且m值的調整也能在小范圍內對系統指標產生影響,所以在一定程度上避免了由于任務變化劇烈所帶來n值的頻繁變化,為n值的調整起到了一定的緩沖作用,實際上,也就是在一定程度上避免了系統頻繁生成和銷毀連接實例所出現的“顛簸”現象。
由于排隊論計算中,算法比較繁瑣,不好由要求的指標變量反求得到輸入變量,所以,在計算中采用了所謂“愿望模型”的試算方法,即逐次給出不同的輸入變量得到不同的指標變量,再依據得到的指標變量,從中選擇一個合適的輸入作為計算結果。對m和n值的計算本質上都是這樣的。
2.3.2 優化計算時用到的主要公式及其推導過程(已知n,m,μ,λ的值)
(1)計算系統損失率:
(2)系統絕對通過能力:A=λ*Pm
(3)平均服務時間:
由:
本文設計了一種通用的連接池技術,包括連接池、管理器、監視器和配置文件等幾部份,并在監視器的設計上,結合排隊論理論,建立了一個訪問服務模型,用以優化連接池的服務質量,以期達到更好的訪問性能。該設計已經在多個系統中應用,其中包括北京交通大學管理信息系統。運行穩定,訪問效率高。
[1]黃汛,程治剛,數據庫連接池技術的應用研究,武漢大學學報(工學版),第35期第一期,2002年2月.
[2]陸傳賚,排隊論[M].北京郵電學院出版社,1994.
[3]陸鳳山,排隊論及其應用[M].湖南科學技術出版社,1984.
[4]孟玉珂,排隊論基礎及應用[M].同濟大學出版社,1989.
[5]華興,排隊論與隨機服務系統[M].上海翻譯出版公司,1987.
[6]劉瓊波,施軍,尤晉元,分布式環境下的訪問控制[M].《計算機研究與發展》,第38卷第6期,2001年6月.
[7]Sun Microsystems,Inc.JavaTM2 SDK,Standard Edition Documentation,Version 1.4.1 September 26,2002.
[8]Bruce Eckel.Java編程思想[M].京京工作室譯,機械工業出版社,1999.4.