標籤:des style blog http color io os 使用 java
一、引言
近年來,隨著 Internet/Intranet 建網技術的飛速發展和在世界範圍內的迅速普及,電子商務的衝擊波又一次在世界範圍內掀起巨浪,各類商務網站吸引著大量使用者的青睞,商務網站的訪問量也就越來越大。這種批量、並發性的訪問使得商務網站對使用者的響應速度會明顯變慢,甚至有可能使使用者無法登陸網站。不堪重荷的商務網站管理公司,除了提高和最佳化網站伺服器的整體效能外,目標也同時轉向程式設計方面,資料庫的串連效能最佳化方面已經成為重點。JAVA 語言的跨平台性、可移植性及安全性等特性,使其應用越來越廣泛,尤其在網路應用中更顯優勢。採用以 JAVA 語言為基礎的串連池技術是解決串連資料庫瓶頸的一種很好的解決方案。它能夠高效地實現資料庫連接的管理,從而使系統效能獲得顯著的改善。
二、傳統模式資料連線的分析
一般情況下,在使用 JAVA 開發基於資料庫的 Web 程式時,傳統的開發模式基本是按以下步驟:首先在主程式(如 Servlet、Beans)中建立資料庫連接;然後進行 SQL 操作,對資料庫中的對象進行插入、修改和刪除等操作;最後斷開資料庫連接。
從圖 1 中可以看出,這種開發模式雖然對程式設計和開發人員來說比較簡單,但也存在很多問題。對於一個簡單的資料庫應用,由於資料庫的訪問不是很頻繁,只需要在訪問資料庫時建立一個串連,用完後就關閉它,這樣做不會明顯地增大系統的開銷。但是對於一個複雜的資料庫應用,情況就完全不同:
- 首先,頻繁的建立、關閉資料庫,會極大的降低系統的效能,增大系統的開銷,導致網站的響應速度下降,嚴重的甚至會造成伺服器的崩潰,成為系統的瓶頸。
- 其次,使用這種傳統的模式,還必須管理資料庫的每一個串連,以確保他們使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體流失,最終將不得不重啟資料庫。、
- 最後,這種開發不能控制被建立的連線物件數,系統資源會被毫無顧及地分配出去,如串連過多,也可能導致記憶體流失,伺服器崩潰。
因此採用運行速度更快、資料庫訪問效率更高的資料庫技術,以提高系統的運行效率將是至關重要的。
三、串連池的解決方案
上述問題的產生根源是在對串連資源的低效管理,採用資料連線池能夠很好地解決此類問題,避免了對於串連的任意、無規則地使用。
串連池是眾多連線物件的“緩衝儲存池”,也就是連線物件的集合體,其核心思想是預先建立一些資料庫連接的對象並放置於記憶體中以備使用(圖 2)。當程式中需要建立資料庫連接時,只需從記憶體對象(串連池)中取一個來用而不用建立。同樣,使用完畢後,只需放回記憶體即可。而串連的建立、斷開都由串連池自身來管理。同時,還可以通過設定串連池的參數來控制串連池中的串連數、每個串連的最大使用次數等等。
串連池主要由 3 部分組成:串連池的建立、串連池中串連的使用管理、串連池的關閉。具體分析涉及以下方面:
(一)串連池的建立
應用程式中要建立的其實是一個靜態串連池,所謂靜態是指串連池中的串連在系統初始化時就已指派好,且不能隨意關閉串連。串連池建立時,根據配置,串連池從資料庫中一次性擷取預設數目的連線物件。這些連線物件作為系統可分配的自由串連,以後所使用的串連都從串連池中擷取,這樣可避免隨意建立、關閉串連所帶來的開銷。
(二)串連池的分配
當使用者需訪問資料庫時,不是直接同資料庫建立串連,而是向串連池申請一個串連。在這裡採用了引用計數的設計方法,該模式在複用資源方面應用得非常廣泛,把該方法運用到對於串連的分配和釋放上,為每一個資料庫連接,保留一個引用記數,用來記錄該串連的使用者的個數。具體的實現方法是:當使用者請求資料庫連接時,首先查看串連池中是否有空閑串連。這裡的空閑是指串連已經建立但當前未使用。如果存在空閑串連,則把串連分配給使用者並作相應處理。主要的處理策略就是設定該串連為已指派狀態,即標記該串連
為正在使用,引用計數加 1。如果沒有空閑串連,則先查看當前所開的串連數是不是已經達到 maxConn(最大串連數),如果沒達到,就給使用者重新建立一個串連,並設定其為已指派狀態;如果已經達到,就只能按設定的maxWaitTime(最大等待時間)進行等待;如果等待 maxWaitTime 後仍沒有空閑串連,就拋出無空閑串連的異常給使用者。為了使串連管理服務有更大的通用性,就必須要考慮到多線程環境,即並發問題。在一個多線程的環境下,必須保證串連池管理自身資料的一致性和串連內部資料的一致性,JAVA 自身通過 synchronized 技術提供了對這方面的很好的支援,這樣就很容易使線程串連管理成為高效、安全的。
(三)使用者等待
串連池類在達到最大串連數時,使用者的請求就要排隊等待。當等待逾時,遞迴調用擷取串連的方法,嘗試再次擷取可用串連。
(四)刪除策略
連線物件動態記錄串連次數。如果一個串連的使用次數超過規定值時,就刪除該串連。這樣做是因為,同一個串連中,每一次串連都會對資料庫的資料操作,都會開闢一個記憶體地區供其使用,當一個串連使用過多,記憶體疊加地區就會加大,所以使用一定次數後,就要釋放資源。另外,當一個串連超過最大空閑時間,就刪除該串連,這樣做也是為了避免記憶體資源的浪費。
(五)釋放策略
當使用者釋放資料庫連接時,先判斷該串連的引用次數是否超過了規定值,如果超過就刪除該串連,並判斷當前串連池內總的串連數是否小於 minConn(最小串連數),若小於就將串連池充滿;如果沒超過就將該串連標記為開放狀態,而不是被關閉,可供再次複用。正是這種策略,保證了資料庫連接的有效使用。
(六)串連池的關閉
當應用程式退出時,應關閉串連池。此時應把在串連池建立時向資料庫申請的連線物件統一歸還給資料庫(即關閉所有資料庫連接),這與串連池的建立正好是一個相反過程。
(七)串連池的配置
資料庫連接池到底要放置多少個串連,才能使系統的效能更佳,這是個配置策略。這裡用 minConn 和maxConn 來限制。minConn 是當應用啟動的時候串連池所建立的串連數,如果過大,啟動將變慢,但是啟動後響應更快;如果過小,啟動加快,但是最初使用的使用者將因為串連池中沒有足夠的串連而不可避免的延緩了執行速度。配置策略是:根據具體的應用需求,給出一個初始的串連池串連數目以及一個串連池可以承受的最大串連數目。串連池管理原則是串連池管理機制的核心。尤其是串連池的分配與釋放,在實際應用中是對效能有很大影響的一個因素。合理的分配與釋放,可以提高串連的複用度,避免頻繁地建立、釋放串連所帶來的系統資源開銷,同時還可以讓使用者訪問的速度加快。
四、串連池的具體實現
首先,在建立串連池之前,我們要確定資料庫的一些基本屬性,如 URL,username,password 等。我們可以先把這些屬性放置在一個檔案(檔案名稱為 PropFile)中,然後,設計一個 GetProperty 類,該類的功能是從檔案PropFile 中讀取資料庫的一些屬性值。這樣做的好處是,串連池不用關心操作的是什麼類型的資料庫,以及資料庫的屬性。當資料庫的類型或屬性發生改變時,我們只要修改檔案 PropFile 即可。GetProperty 類中最重要的函數是建構函式,該函數的主要功能是從檔案 PropFile 中讀取資料庫的屬性值。其核心代碼如下:
public GetProperty(String infile){ InputStream = InStream.getClass(); getResourceAsStream(infile); Properties Props = new Properties; try { Props.load(InStream); driver = Props.getProperty("driver"); url = Props.getProperty("url"); username = Props.getProperty("username"); password = Props.getProperty("password"); }catch(Exception e) {// 輸出出錯資訊 return; } }
現在可以開始建立串連池了,串連池必須提供幾個最基本的介面,下面我們以虛擬碼的形式給出這幾個介面的定義。
public class ConnectionPool { private Connection CreateConn() { // 建立新的串連 // 首先檢查有無空閑串連,如果沒有,再檢查串連是否達到了上限, // 如果串連數沒有達到上限,則建立新的串連。 } public synchronized Connection getConnection() { // 把使用者釋放的串連放入串連池中 } public synchronized void release() { // 關閉所有串連 } }
串連池建立好之後,還要建立一個管理類(ConnectionPoolManager)來管理串連池,我們仍然以虛擬碼的形式給出這個類的定義。
public class ConnectionPoolManager { private void init() { // 管理類的初始化 } public Connection getConnection(String poolname) { // 從指定的串連池中取得一個資料庫連接 } public void backconn(String poolname, Connection conn) { // 把使用者釋放的串連歸還給指定的串連池 } public synchronized void close { // 關閉一個串連池 } public synchronized void release() { // 釋放所有的串連 } public synchronized void destroy() { // 銷毀一個串連池 } }
對於大型的、複雜的、網路化的資料庫應用系統而言,恰當的使用串連池技術,可以大大地提高程式的執行效率。
五、結束語
總之,由於 JAVA 有著其它語言不可比擬的優點,JAVA 的應用將越來越廣泛,筆者著重闡述了 JAVA資料庫應用中串連池的基本工作機制,並實現了一個基本的串連池,對開發高效能的資料庫應用程式有一定的實用和參考價值。
摘自:尚 弘[ 參考文獻][1 ] 普悠瑪數位科技有限公司. JAVA2 程式設計. 北京:清華大學出版社,2002[2 ] 光軍、胡波.JSP 應用開發執行個體詳解. 北京:北京航天航空大學出版社,2002[3] [美]Joe Zuffoletto.BEA weblogic server bible. 北京:電子工業出版社,2003[4] 李世祥. Structs 架構應用與開發. 大連:東軟電子出版社,2007
JAVA 資料庫連接池(虛擬碼,簡單易讀)