鏈接池的基本工做原理

鏈接池的基本工做原理java

  一、基本概念及原理數據庫

  由上面的分析能夠看出,問題的根源就在於對數據庫鏈接資源的低效管理。咱們知道,對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是爲了解決資源的頻繁分配?釋放所形成的問題。爲解決上述問題,能夠採用數據庫鏈接池技術。數據庫鏈接池的基本思想就是爲數據庫鏈接 創建一個「緩衝池」。預先在緩衝池中放入必定數量的鏈接,當須要創建數據庫鏈接時,只需從「緩衝池」中取出一個,使用完畢以後再放回去。咱們能夠經過設定 鏈接池最大鏈接數來防止系統無盡的與數據庫鏈接。更爲重要的是咱們能夠經過鏈接池的管理機制監視數據庫的鏈接的數量?使用狀況,爲系統開發?測試及性能調 整提供依據。設計模式

  二、服務器自帶的鏈接池安全

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

  鏈接池關鍵問題分析多線程

  一、併發問題併發

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

  public synchronized Connection getConnection()函數

  二、多數據庫服務器和多用戶性能

  對於大型的企業級應用,經常須要同時鏈接不一樣的數據庫(如鏈接Oracle和Sybase)。如何鏈接不一樣的數據庫呢?咱們採用的策略是:設計 一個符合單例模式的鏈接池管理類,在鏈接池管理類的惟一實例被建立時讀取一個資源文件,其中資源文件中存放着多個數據庫的url地址()?用戶名()?密 碼()等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據資源文件提 供的信息,建立多個鏈接池類的實例,每個實例都是一個特定數據庫的鏈接池。鏈接池管理類實例爲每一個鏈接池實例取一個名字,經過不一樣的名字來管理不一樣的連 接池。

  對於同一個數據庫有多個用戶使用不一樣的名稱和密碼訪問的狀況,也能夠經過資源文件處理,即在資源文件中設置多個具備相同url地址,但具備不一樣用戶名和密碼的數據庫鏈接信息。

  三、事務處理

  咱們知道,事務具備原子性,此時要求對數據庫的操做符合「ALL-ALL-NOTHING」原則,即對於一組SQL語句要麼全作,要麼全不作。

  在Java語言中,Connection類自己提供了對事務的支持,能夠經過設置Connection的AutoCommit屬性爲false,而後顯式的調用commit或rollback方法來實現。但要高效的進行Connection複用,就必須提供相應的事務支持機制。可採用 每個事務獨佔一個鏈接來實現,這種方法能夠大大下降事務管理的複雜性。

  四、鏈接池的分配與釋放

  鏈接池的分配與釋放,對系統的性能有很大的影響。合理的分配與釋放,能夠提升鏈接的複用度,從而下降創建新鏈接的開銷,同時還能夠加快用戶的訪問速度。

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

  五、鏈接池的配置與維護

  鏈接池中到底應該放置多少鏈接,才能使系統的性能最佳?系統可採起設置最小鏈接數(minConn)和最大鏈接數(maxConn)來控制鏈接 池中的鏈接。最小鏈接數是系統啓動時鏈接池所建立的鏈接數。若是建立過多,則系統啓動就慢,但建立後系統的響應速度會很快;若是建立過少,則系統啓動的很 快,響應起來卻慢。這樣,能夠在開發時,設置較小的最小鏈接數,開發起來會快,而在系統實際使用時設置較大的,由於這樣對訪問客戶來講速度會快些。最大連 接數是鏈接池中容許鏈接的最大數目,具體設置多少,要看系統的訪問量,可經過反覆測試,找到最佳點。

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

  鏈接池的實現

  一、鏈接池模型

  本文討論的鏈接池包括一個鏈接池類(DBConnectionPool)和一個鏈接池管理類(DBConnetionPoolManager)。鏈接池類是對某一數據庫全部鏈接的「緩衝池」,主要實現如下功能:①從鏈接池獲取或建立可用鏈接;②使用完畢以後,把鏈接返還給鏈接池;③在系統關閉前,斷開全部鏈接並釋放鏈接佔用的系統資源;④還可以處理無效鏈接(原來登記爲可用的鏈接,因爲某種緣由 再也不可用,如超時,通信問題),並可以限制鏈接池中的鏈接總數不低於某個預約值和不超過某個預約值。

  鏈接池管理類是鏈接池類的外覆類(wrapper),符合單例模式,即系統中只能有一個鏈接池管理類的實例。其主要用於對多個鏈接池對象的管 理,具備如下功能:①裝載並註冊特定數據庫的JDBC驅動程序;②根據屬性文件給定的信息,建立鏈接池對象;③爲方便管理多個鏈接池對象,爲每個鏈接池 對象取一個名字,實現鏈接池名字與其實例之間的映射;④跟蹤客戶使用鏈接狀況,以便須要是關閉鏈接釋放資源。鏈接池管理類的引入主要是爲了方便對多個鏈接 池的使用和管理,如系統須要鏈接不一樣的數據庫,或鏈接相同的數據庫但因爲安全性問題,須要不一樣的用戶使用不一樣的名稱和密碼。

  二、鏈接池實現

  下面給出鏈接池類和鏈接池管理類的主要屬性及所要實現的基本接口:

  1. public class DBConnectionPool implements TimerListener{ 
  2. private int checkedOut;//已被分配出去的鏈接數 
  3. private ArrayList freeConnections=new ArrayList(); 
  4. //容器,空閒池,根據//建立時間順序存放已建立但還沒有分配出去的鏈接 
  5. private int minConn;//鏈接池裏鏈接的最小數量 
  6. private int maxConn;//鏈接池裏容許存在的最大鏈接數 
  7. private String name;//爲這個鏈接池取個名字,方便管理 
  8. private String password;//鏈接數據庫時須要的密碼 
  9. private String url;//所要建立鏈接的數據庫的地址 
  10. private String user;//鏈接數據庫時須要的用戶名 
  11. public Timer timer;//定時器 
  12. public DBConnectionPool(String name,String URL,String user, 
  13. String password,int maxConn)//公開的構造函數 
  14. public synchronized void freeConnection(Connection con) 
  15. //使用完畢以後,把鏈接返還給空閒池 
  16. public synchronized Connection getConnection(long timeout) 
  17. //獲得一個鏈接,timeout是等待時間 
  18. public synchronized void release() 
  19. //斷開全部鏈接,釋放佔用的系統資源 
  20. private Connection newConnection() 
  21. //新建一個數據庫鏈接 
  22. public synchronized void TimerEvent() 
  23. //定時器事件處理函數 
  24. public class DBConnectionManager { 
  25. static private DBConnectionManager instance; 
  26. //鏈接池管理類的惟一實例 
  27. static private int clients;//客戶數量 
  28. private ArrayList drivers=new ArrayList(); 
  29. //容器,存放數據庫驅動程序 
  30. private HashMap pools = new HashMap(); 
  31. //以name/value的形式存取鏈接池對象的名字及鏈接池對象 
  32. static synchronized public DBConnectionManager getInstance() 
  33. /**若是惟一的實例instance已經建立,直接返回這個實例;不然,調用私有構造函數,
  34. 建立鏈接池管理類的惟一實例*/ 
  35. private DBConnectionManager() 
  36. //私有構造函數,在其中調用初始化函數init() 
  37. public void freeConnection(String name,Connection con) 
  38. //釋放一個鏈接,name是一個鏈接池對象的名字 
  39. public Connection getConnection(String name) 
  40. //從名字爲name的鏈接池對象中獲得一個鏈接 
  41. public Connection getConnection(String name,long time) 
  42. //從名字爲name的鏈接池對象中取得一個鏈接,time是等待時間 
  43. public synchronized void release()//釋放全部資源 
  44. private void createPools(Properties props) 
  45. //根據屬性文件提供的信息,建立一個或多個鏈接池 
  46. private void init()//初始化鏈接池管理類的惟一實例,由私有構造函數調用 
  47. private void loadDrivers(Properties props)//裝載數據庫驅動程序 

  三、鏈接池使用

  上面所實現的鏈接池在程序開發時如何應用到系統中呢?下面以Servlet爲例說明鏈接池的使用。

  Servlet的生命週期是:在開始創建servlet時,調用其初始化(init)方法。以後每一個用戶請求都致使一個調用前面創建的實例的service方法的線程。最後,當服務器決定卸載一個servlet時,它首先調用該servlet的destroy方法。

  根據servlet的特色,咱們能夠在初始化函數中生成鏈接池管理類的惟一實例(其中包括建立一個或多個鏈接池)。如:

  1. public void init() throws ServletException 
  2. connMgr=DBConnectionManager.getInstance(); 
  3. 而後就能夠在service方法中經過鏈接池名稱使用鏈接池,執行數據庫操做。最後在destroy方法中釋放佔用的系統資源,如: 
  4. public void destroy(){ 
  5. connMgr.release(); 
  6. super.destroy(); 

  結束語

  在使用JDBC進行與數據庫有關的應用開發中,數據庫鏈接的管理是一個難點。不少時候,鏈接的混亂管理所形成的系統資源開銷過大成爲制約大型企 業級應用效率的瓶頸。對於衆多用戶訪問的Web應用,採用數據庫鏈接技術的系統在效率和穩定性上比採用傳統的其餘方式的系統要好不少。本文闡述了使用JDBC訪問數據庫的技術?討論了基於鏈接池技術的數據庫鏈接管理的關鍵問題並給出了一個實現模型。文章所給出的是鏈接池管理程序的一種基本模式,爲提升 系統的總體性能,在此基礎上還能夠進行不少有意義的擴展。

相關文章
相關標籤/搜索