基於JDBC的資料庫連接池技術研究與應用

來源:互聯網
上載者:User
資料|資料庫|資料庫連接    摘 要 本文介紹了Java訪問資料庫的原理及其存在的問題,提出瞭解決辦法-資料庫連接池,並對其關鍵問題進行了分析,構建了一個簡便易用的串連池並結合當前熱門技術Servlet說明了其如何在開發時使用。

  關鍵詞 JDBC,Jsp/Servlet,資料庫連接池,多資料庫伺服器和多使用者,多線程

   引言

  近年來,隨著Internet/Intranet建網技術的飛速發展和在世界範圍內的迅速普及,電腦

  應用程式已從傳統的案頭應用轉到Web應用。基於B/S(Browser/Server)架構的3層開發模式逐漸取代C/S(Client/Server)架構的開發模式,成為開發企業級應用和電子商務普遍採用的技術。在Web應用開發的早期,主要使用的技術是CGI﹑ASP﹑PHP等。之後,Sun公司推出了基於Java語言的Servlet+Jsp+JavaBean技術。相比傳統的開發技術,它具有跨平台﹑安全﹑有效﹑可移植等特性,這使其更便於使用和開發。

   Java應用程式訪問資料庫的基本原理

  在Java語言中,JDBC(Java DataBase Connection)是應用程式與資料庫溝通的橋樑,

  即Java語言通過JDBC技術訪問資料庫。JDBC是一種“開放”的方案,它為資料庫應用開發人員﹑資料庫前台工具開發人員提供了一種標準的應用程式設計介面,使開發人員可以用純Java語言編寫完整的資料庫應用程式。JDBC提供兩種API,分別是面向開發人員的API和面向底層的JDBC驅動程式API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與資料庫的串連。

  一般來說,Java應用程式訪問資料庫的過程(如圖1所示)是:

  ①裝載資料庫驅動程式;

  ②通過JDBC建立資料庫連接;

  ③訪問資料庫,執行SQL語句;

  ④斷開資料庫連接。


圖1 Java資料庫訪問機制


  JDBC作為一種資料庫訪問技術,具有簡單易用的優點。但使用這種模式進行Web應用

  程式開發,存在很多問題:首先,每一次Web請求都要建立一次資料庫連接。建立串連是一個費時的活動,每次都得花費0.05s~1s的時間,而且系統還要分配記憶體資源。這個時間對於一次或幾次資料庫操作,或許感覺不出系統有多大的開銷。可是對於現在的Web應用,尤其是大型電子商務網站,同時有幾百人甚至幾千人線上是很正常的事。在這種情況下,頻繁的進行資料庫連接操作勢必佔用很多的系統資源,網站的響應速度必定下降,嚴重的甚至會造成伺服器的崩潰。不是危言聳聽,這就是制約某些電子商務網站發展的技術瓶頸問題。其次,對於每一次資料庫連接,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體流失,最終將不得不重啟資料庫。還有,這種開發不能控制被建立的連線物件數,系統資源會被毫無顧及的分配出去,如串連過多,也可能導致記憶體流失,伺服器崩潰。

  資料庫連接池(connection pool)的工作原理

  1、基本概念及原理

  由上面的分析可以看出,問題的根源就在於對資料庫連接資源的低效管理。我們知道,

  對於共用資源,有一個很著名的設計模式:資源集區(Resource Pool)。該模式正是為瞭解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以採用資料庫連接池技術。資料庫連接池的基本思想就是為資料庫連接建立一個“緩衝池”。預先在緩衝池中放入一定數量的串連,當需要建立資料庫連接時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定串連池最大串連數來防止系統無盡的與資料庫連接。更為重要的是我們可以通過串連池的管理機制監視資料庫的串連的數量﹑使用方式,為系統開發﹑測試及效能調整提供依據。串連池的基本工作原理見下圖2。


圖2 串連池的基本工作原理
  2、伺服器內建的串連池

  JDBC的API中沒有提供串連池的方法。一些大型的WEB應用伺服器如BEA的WebLogic和IBM的WebSphere等提供了串連池的機制,但是必須有其第三方的專用類方法支援串連池的用法。

  串連池關鍵問題分析

  1、並發問題

  為了使串連管理服務具有最大的通用性,必須考慮多線程環境,即並發問題。這個問題相對比較好解決,因為Java語言自身提供了對並發管理的支援,使用synchronized關鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如:

public synchronized Connection getConnection()


  2、多資料庫伺服器和多使用者

  對於大型的企業級應用,常常需要同時串連不同的資料庫(如串連Oracle和Sybase)。如何串連不同的資料庫呢?我們採用的策略是:設計一個符合單例模式的串連池管理類,在串連池管理類的唯一執行個體被建立時讀取一個資源檔,其中資源檔中存放著多個資料庫的url地址(<poolName.url>)﹑使用者名稱(<poolName.user>)﹑密碼(<poolName.password>)等資訊。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據資源檔提供的資訊,建立多個串連池類的執行個體,每一個執行個體都是一個特定資料庫的串連池。串連池管理類執行個體為每個串連池執行個體取一個名字,通過不同的名字來管理不同的串連池。

  對於同一個資料庫有多個使用者使用不同的名稱和密碼訪問的情況,也可以通過資源檔處理,即在資源檔中設定多個具有相同url地址,但具有不同使用者名稱和密碼的資料庫連接資訊。

  3、交易處理

  我們知道,事務具有原子性,此時要求對資料庫的操作符合“ALL-ALL-NOTHING”原則,即對於一組SQL語句要麼全做,要麼全不做。

  在Java語言中,Connection類本身提供了對事務的支援,可以通過設定Connection的AutoCommit屬性為false,然後顯式的調用commit或rollback方法來實現。但要高效的進行Connection複用,就必須提供相應的事務支援機制。可採用每一個事務獨佔一個串連來實現,這種方法可以大大降低交易管理的複雜性。

  4、串連池的分配與釋放

  串連池的分配與釋放,對系統的效能有很大的影響。合理的分配與釋放,可以提高串連的複用度,從而降低建立新串連的開銷,同時還可以加快使用者的訪問速度。

  對於串連的管理可使用空閑池。即把已經建立但尚未分配出去的串連按建立時間存放到一個空閑池中。每當使用者請求一個串連時,系統首先檢查空閑池內有沒有空閑串連。如果有就把建立時間最長(通過容器的順序存放實現)的那個串連分配給他(實際是先做串連是否有效判斷,如果可用就分配給使用者,如不可用就把這個串連從空閑池刪掉,重新檢測空閑池是否還有串連);如果沒有則檢查當前所開串連池是否達到串連池所允許的最大串連數(maxConn),如果沒有達到,就建立一個串連,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有串連被釋放出來就可以把這個串連分配給等待的使用者,如果等待時間超過預定時間timeout,則返回空值(null)。系統對已經分配出去正在使用的串連只做計數,當使用完後再返還給空閑池。對於空閑串連的狀態,可開闢專門的線程定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可採取不開闢專門線程,只是在分配前檢測的方法。

  5、串連池的配置與維護

  串連池中到底應該放置多少串連,才能使系統的效能最佳?系統可採取設定最小串連數(minConn)和最大串連數(maxConn)來控制串連池中的串連。最小串連數是系統啟動時串連池所建立的串連數。如果建立過多,則系統啟動就慢,但建立後系統的響應速度會很快;如果建立過少,則系統啟動的很快,響應起來卻慢。這樣,可以在開發時,設定較小的最小串連數,開發起來會快,而在系統實際使用時設定較大的,因為這樣對訪問客戶來說速度會快些。最大串連數是串連池中允許串連的最大數目,具體設定多少,要看系統的訪問量,可通過反覆測試,找到最佳點。

  如何確保串連池中的最小串連數呢?有動態和靜態兩種策略。動態即每隔一定時間就對串連池進行檢測,如果發現串連數量小於最小串連數,則補充相應數量的新串連,以保證串連池的正常運轉。靜態是發現空閑串連不夠時再去檢查。

  串連池的實現

  1、串連池模型

  本文討論的串連池包括一個串連池類(DBConnectionPool)和一個串連池管理類(DBConnetionPoolManager)。串連池類是對某一資料庫所有串連的“緩衝池”,主要實現以下功能:①從串連池擷取或建立可用串連;②使用完畢之後,把串連返還給串連池;③在系統關閉前,斷開所有串連並釋放串連佔用的系統資源;④還能夠處理無效串連(原來登記為可用的串連,由於某種原因不再可用,如逾時,通訊問題),並能夠限制串連池中的串連總數不低於某個預定值和不超過某個預定值。

  串連池管理類是串連池類的外覆類(wrapper),符合單例模式,即系統中只能有一個串連池管理類的執行個體。其主要用於對多個串連池對象的管理,具有以下功能:①裝載並註冊特定資料庫的JDBC驅動程式;②根據屬性檔案給定的資訊,建立串連池對象;③為方便管理多個串連池對象,為每一個串連池對象取一個名字,實現串連池名字與其執行個體之間的映射;④跟蹤客戶使用串連情況,以便需要是關閉串連釋放資源。串連池管理類的引入主要是為了方便對多個串連池的使用和管理,如系統需要串連不同的資料庫,或串連相同的資料庫但由於安全性問題,需要不同的使用者使用不同的名稱和密碼。

  2、串連池實現

  下面給出串連池類和串連池管理類的主要屬性及所要實現的基本介面:

public class DBConnectionPool implements TimerListener{
private int checkedOut;//已被分配出去的串連數
private ArrayList freeConnections = new ArrayList();//容器,空閑池,根據//建立時間順序存放已建立但尚未分配出去的串連
private int minConn;//串連池裡串連的最小數量
private int maxConn;//串連池裡允許存在的最大串連數
private String name;//為這個串連池取個名字,方便管理
private String password;//串連資料庫時需要的密碼
private String url;//所要建立串連的資料庫的地址
private String user;//串連資料庫時需要的使用者名稱
public Timer timer;//定時器
public DBConnectionPool(String name, String URL, String user, String
password, int maxConn)//公開的建構函式
public synchronized void freeConnection(Connection con) //使用完畢之後,//把串連返還給空閑池
public synchronized Connection getConnection(long timeout)//得到一個串連,//timeout是等待時間
public synchronized void release()//斷開所有串連,釋放佔用的系統資源
private Connection newConnection()//建立一個資料庫連接
public synchronized void TimerEvent() //定時器事件處理函數

}

public class DBConnectionManager {
static private DBConnectionManager instance;//串連池管理類的唯一執行個體
static private int clients;//客戶數量
private ArrayList drivers = new ArrayList();//容器,存放資料庫驅動程式

private HashMap pools = new HashMap ();//以name/value的形式存取串連池//對象的名字及串連池對象
static synchronized public DBConnectionManager getInstance()//如果唯一的//執行個體instance已經建立,直接返回這個執行個體;否則,調用私人建構函式,創//建串連池管理類的唯一執行個體

private DBConnectionManager()//私人建構函式,在其中調用初始化函數init()

public void freeConnection(String name, Connection con)// 釋放一個串連,//name是一個串連池對象的名字

public Connection getConnection(String name)//從名字為name的串連池對象//中得到一個串連

public Connection getConnection(String name, long time)//從名字為name

//的串連池對象中取得一個串連,time是等待時間

public synchronized void release()//釋放所有資源

private void createPools(Properties props)//根據屬性檔案提供的資訊,建立//一個或多個串連池

private void init()//初始化串連池管理類的唯一執行個體,由私人建構函式調用

private void loadDrivers(Properties props)//裝載資料庫驅動程式

}


  3、串連池使用

  上面所實現的串連池在程式開發時如何應用到系統中呢?下面以Servlet為例說明串連池的使用。

  Servlet的生命週期是:在開始建立servlet時,調用其初始化(init)方法。之後每個使用者請求都導致一個調用前面建立的執行個體的service方法的線程。最後,當伺服器決定卸載一個servlet時,它首先調用該servlet的 destroy方法。

  根據servlet的特點,我們可以在初始化函數中產生串連池管理類的唯一執行個體(其中包括建立一個或多個串連池)。如:

public void init() throws ServletException
{
 connMgr = DBConnectionManager.getInstance();
}


  然後就可以在service方法中通過串連池名稱使用串連池,執行資料庫操作。最後在destroy方法中釋放佔用的系統資源,如:

public void destroy() {
 connMgr.release(); super.destroy();
}


   結束語

  在使用JDBC進行與資料庫有關的應用開發中,資料庫連接的管理是一個痛點。很多時候,串連的混亂管理所造成的系統資源開銷過大成為制約大型企業級應用效率的瓶頸。對於眾多使用者訪問的Web應用,採用資料庫連接技術的系統在效率和穩定性上比採用傳統的其他方式的系統要好很多。本文闡述了使用JDBC訪問資料庫的技術﹑討論了基於串連池技術的資料庫連接管理的關鍵問題並給出了一個實現模型。文章所給出的是串連池管理程式的一種基本模式,為提高系統的整體效能,在此基礎上還可以進行很多有意義的擴充。



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。