標籤:style blog http ar io color os 使用 sp
一、為什麼我們要用串連池技術?
前面的資料庫連接的建立及關閉資源的方法有些缺陷。統艙傳統資料庫訪問方式:一次資料庫訪問對應一個物理串連,每次操作資料庫都要開啟、關閉該物理串連, 系統效能嚴重受損。
解決方案:資料庫連接池(Connection Pool)。
系統初始運行時,主動建立足夠的串連,組成一個池.每次應用應用程式請求資料庫連接時,無需重新開啟串連,而是從池中取出已有的串連,使用完後,不再關閉,而是歸還。
二、串連池主要由三部分組成:串連池的建立、串連池中串連的使用管理、串連池的關閉。
三、串連池技術的核心思想
串連複用,通過建立一個資料庫連接池以及一套串連使用、分配、管理原則,使得該串連池中的串連可以得到高效、安全的複用,避免了資料庫連接頻繁建立、關閉的開銷。
1.串連池的建立
在系統初始化時,根據相應的配置建立串連並放置在串連池中,以便需要使用時能從串連池中擷取,這樣就可以避免串連隨意的建立、關閉造成的開銷。
2.串連池中串連的使用管理
串連池管理原則是串連池機制的核心。當串連池建立後,如何對串連池中的串連進行管理,解決好串連池內串連的分配和釋放,對系統的效能有很大的影響。串連的合理分配、釋放可提高串連的複用,降低了系統建立新串連的開銷,同時也加速了使用者的訪問速度。
採用的方法是一個很有名的設計模式:Reference Counting(引用記數)。該模式在複用資源方面應用的非常廣泛,把該方法運用到對於串連的分配釋放上,為每一個資料庫連接,保留一個引用記數,用來記錄該串連的使用者的個數。
(1)當客戶請求資料庫連接時,首先查看串連池中是否有空閑串連(指當前沒有分配出去的串連)。如果存在空閑串連,則把串連分配給客戶並作相應處理(即標記該串連為正在使用,引用計數加1)。如果沒有空閑串連,則查看當前所開的串連數是不是已經達到maxConn(最大串連數),如果沒達到就重新建立一個串連給請求的客戶;如果達到就按設定的maxWaitTime(最大等待時間)進行等待,如果等待maxWaitTime後仍沒有空閑串連,就拋出無空閑串連的異常給使用者。
(2)當客戶釋放資料庫連接時,先判斷該串連的引用次數是否超過了規定值,如果超過就刪除該串連,並判斷當前串連池內總的串連數是否小於minConn(最小串連數),若小於就將串連池充滿;如果沒超過就將該串連標記為開放狀態,可供再次複用。可以看出正是這套策略保證了資料庫連接的有效複用,避免頻繁地建立、釋放串連所帶來的系統資源開銷。
3.串連池的關閉
當應用程式退出時,應關閉串連池,此時應把在串連池建立時向資料庫申請的連線物件統一歸還給資料庫(即關閉所有資料庫連接),這與串連池的建立正好是一個相反過程。
我們採用DBCP(DataBase connection pool),資料庫連接池。DBCP(是 apache 上的一個 java 串連池項目,也是 tomcat 使用的串連池組件。單獨使用dbcp需要3個包:commons-dbcp.jar,commons-pool.jar,commons-collections.jar由於建立資料庫連接是一個非常耗時耗資源的行為,所以通過串連池預先同資料庫建立一些串連,放在記憶體中,應用程式需要建立資料庫連接時直接到串連池中申請一個就行,用完後再放回去。
四、串連池的實現
建立一個java工程並匯入相應的包。
設定檔:
1 jdbc.driver=com.mysql.jdbc.Driver2 jdbc.url=jdbc:mysql://localhost:3306/csdn3 jdbc.user=root4 jdbc.password=1234565 initsize=16 maxactive=17 maxwait=50008 maxidle=19 minidle=1
dbcp的基本配置的介紹
1.initialSize :串連池啟動時建立的初始化串連數量(預設值為0)
2.maxActive :串連池中可同時串連的最大的串連數(預設值為8,調整為20,高峰單機器在20並發左右,自己根據應用情境定)
3.maxIdle:串連池中最大的閒置串連數,超過的空閑串連將被釋放,如果設定為負數表示不限制(預設為8個,maxIdle不能設定太小,因為假如在高負載的情況下,串連的開啟時間比關閉的時間快,會引起串連池中idle的個數 上升超過maxIdle,而造成頻繁的串連銷毀和建立,類似於jvm參數中的Xmx設定)
4.minIdle:串連池中最小的閒置串連數,低於這個數量會被建立新的串連(預設為0,調整為5,該參數越接近maxIdle,效能越好,因為串連的建立和銷毀,都是需要消耗資源的;但是不能太大,因為在機器很閒置時候,也會建立低於minidle個數的串連,類似於jvm參數中的Xmn設定)
5.maxWait :最大等待時間,當沒有可用串連時,串連池等待串連釋放的最大時間,超過該時間限制會拋出異常,如果設定-1表示無限等待(預設為無限,調整為60000ms,避免因線程池不夠用,而導致請求被無限制掛起)
DBUtil源碼如下:
1 package com.daliu.jdbc; 2 3 import java.io.InputStream; 4 import java.sql.Connection; 5 import java.sql.SQLException; 6 import java.util.Properties; 7 8 import org.apache.commons.dbcp.BasicDataSource; 9 10 /** 11 * 使用串連池技術管理資料庫串連 12 */ 13 public class DBUtil { 14 15 //資料庫連接池 16 private static BasicDataSource dbcp; 17 18 //為不同線程管理串連 19 private static ThreadLocal<Connection> tl; 20 21 //通過設定檔來擷取資料庫參數 22 static{ 23 try{ 24 Properties prop 25 = new Properties(); 26 27 InputStream is 28 = DBUtil.class.getClassLoader() 29 .getResourceAsStream( 30 "com/daliu/jdbc/db.properties"); 31 32 prop.load(is); 33 is.close(); 34 35 //一、初始化串連池 36 dbcp = new BasicDataSource(); 37 38 39 //設定驅動 (Class.forName()) 40 dbcp.setDriverClassName(prop.getProperty("jdbc.driver")); 41 //設定url 42 dbcp.setUrl(prop.getProperty("jdbc.url")); 43 //設定資料庫使用者名稱 44 dbcp.setUsername(prop.getProperty("jdbc.user")); 45 //設定資料庫密碼 46 dbcp.setPassword(prop.getProperty("jdbc.password")); 47 //初始串連數量 48 dbcp.setInitialSize( 49 Integer.parseInt( 50 prop.getProperty("initsize") 51 ) 52 ); 53 //串連池允許的最大串連數 54 dbcp.setMaxActive( 55 Integer.parseInt( 56 prop.getProperty("maxactive") 57 ) 58 ); 59 //設定最大等待時間 60 dbcp.setMaxWait( 61 Integer.parseInt( 62 prop.getProperty("maxwait") 63 ) 64 ); 65 //設定最小空閑數 66 dbcp.setMinIdle( 67 Integer.parseInt( 68 prop.getProperty("minidle") 69 ) 70 ); 71 //設定最大空閑數 72 dbcp.setMaxIdle( 73 Integer.parseInt( 74 prop.getProperty("maxidle") 75 ) 76 ); 77 //初始化執行緒區域 78 tl = new ThreadLocal<Connection>(); 79 }catch(Exception e){ 80 e.printStackTrace(); 81 } 82 } 83 84 /** 85 * 擷取資料庫連接 86 * @return 87 * @throws SQLException 88 */ 89 public static Connection getConnection() throws SQLException{ 90 /* 91 * 通過串連池擷取一個空閑串連 92 */ 93 Connection conn 94 = dbcp.getConnection(); 95 tl.set(conn); 96 return conn; 97 } 98 99 100 /**101 * 關閉資料庫連接102 */103 public static void closeConnection(){104 try{105 Connection conn = tl.get();106 if(conn != null){107 /*108 * 通過串連池擷取的Connection109 * 的close()方法實際上並沒有將110 * 串連關閉,而是將該連結歸還。111 */112 conn.close();113 tl.remove();114 } 115 }catch(Exception e){116 e.printStackTrace();117 }118 }119 120 /**121 * 測試是否串連成功122 * @param args123 * @throws SQLException124 */125 public static void main(String[] args) throws SQLException {126 System.out.println(getConnection());127 }128 }
效果如下:
串連池技術解密,串連池對我們不再陌生