1. 程式人生 > >Java連線池詳解

Java連線池詳解

http://www.javaweb1024.com/java/JavaWebzhongji/2015/06/01/736.html

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

為什麼使用連線池

連線,是我們的程式語言與資料庫互動的一種方式。我們經常會聽到這麼一句話“資料庫連線很昂貴“。

有人接受這種說法,卻不知道它的真正含義。因此,下面通過例項解釋它究竟是什麼。

下面是Mysql資料庫建立連線的的一段程式碼:

[java] view plaincopyprint?

  1. String connUrl ="jdbc:mysql://your.database.domain/yourDBname";  

  2. Class.forName("com.mysql.jdbc.Driver");  

  3. Connection con =DriverManager.getConnection (connUrl);  


當我們建立了一個Connection物件,它在內部都執行了什麼:

1.“DriverManager”檢查並註冊驅動程式;

2.“com.mysql.jdbc.Driver”就是我們註冊了的驅動程式,它會在驅動程式類中呼叫“connect(url…)”方法。

3.com.mysql.jdbc.Driver的connect方法根據我們請求的“connUrl”,建立一個“Socket連線”,連線到IP為“your.database.domain”,預設埠3306的資料庫。

4.建立的Socket連線將被用來查詢我們指定的資料庫,並最終讓程式返回得到一個結果。

簡單的獲取一個連線,系統卻要在背後做很多消耗資源的事情,大多時候,建立連線的時間比執行sql語句的時間還要長。

傳統的獲取連線方式如下圖所示:


使用者每次請求都需要向資料庫獲得連結,而資料庫建立連線通常需要消耗相對較大的資源,建立時間也較長。假設網站一天10萬訪問量,資料庫伺服器就需要建立10萬次連線,極大的浪費資料庫的資源,並且極易造成資料庫伺服器記憶體溢位、拓機。

採用連線池技術後的過程如下:


資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現的尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池負責分配,管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是重新建立一個。

需要注意的問題

1、併發問題

為了使連線管理服務具有最大的通用性,必須考慮多執行緒環境,即併發問題。這個問題相對比較好解決,因為各個語言自身提供了對併發管理的支援像java,c#等等,使用synchronized(java)、lock(C#)關鍵字即可確保執行緒是同步的。

2、事務處理

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

我們知道當2個執行緒公用一個連線Connection物件,而且各自都有自己的事務要處理時候,對於連線池是一個很頭疼的問題,因為即使Connection類提供了相應的事務支援,可是我們仍然不能確定那個資料庫操作是對應那個事務的,這是由於我們有2個執行緒都在進行事務操作而引起的。為此我們可以使用每一個事務獨佔一個連線來實現,雖然這種方法有點浪費連線池資源但是可以大大降低事務管理的複雜性。

3、連線池的分配與釋放

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

對於連線的管理可使用一個List。即把已經建立的連線都放入List中去統一管理。每當使用者請求一個連線時,系統檢查這個List中有沒有可以分配的連線。如果有就把那個最合適的連線分配給他(如何能找到最合適的連線文章將在關鍵議題中指出);如果沒有就丟擲一個異常給使用者,List中連線是否可以被分配由一個執行緒來專門管理。

4、連線池的配置與維護

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

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

Tomcat連線池

Tomcat預設使用的是DBCP資料庫連線池,其實從本質上講,Tomcat是利用Apache Commons DBCP來實現的,只不過把特定的功能整合到了tomcat-dbcp.jar包中。

使用法法如下:

步驟1:

在Tomcat中Context.xml中新增

[html] view plaincopyprint?

  1. <!--  path表示站點的訪問方式 -->

  2. <!--    例:http://localhost:8080/test 配置為/test -->

  3. <!-- docBase="fileLocation" 應用儲存的實際路徑,沒有的話則從webapps目錄找 -->

  4. <!-- Context標籤內的這些屬性都可以省略不寫,使用預設的設定 -->

  5. <Contextpath="/TomcatDbPools"docBase="TomcatDbPools"debug="0"reloadable="true">

  6.             <!--     使用DBCP配置的資料來源        -->

  7. <Resource

  8. <!-- 指定資源池的Resource的JNDI的名字,就是給連線池起的名字 -->

  9.        name="jdbc/mysql_connect"

  10. <!-- 管理許可權,指定管理Resource的Manager,可以是Container或Application -->

  11.        auth="Container"

  12. <!--指出Resource所屬的類名,是什麼型別的資料來源-->

  13.        type="javax.sql.DataSource"

  14. <!-- 資料庫驅動類 -->

  15.        driverClassName="com.mysql.jdbc.Driver"

  16. <!-- 資料庫連線url-->

  17.        url=" jdbc:mysql://localhost:3306/test"

  18. <!-- 資料庫使用者名稱 -->

  19.        username="admin"

  20. <!-- 資料庫密碼 -->

  21.        password="123456"

  22. <!-- 連線池最大啟用的連線數,設為0表示無限制-->

  23.        maxActive="100"

  24. <!-- 連線池中最多可空閒的連線數 -->

  25.        maxIdle="30"

  26. <!-- 為連線最大的等待時間,單位毫秒,如果超過此時間將接到異常。設為-1表示無限制-->

  27.        maxWait="10000"/>

  28. </context>

注:還可以用minIdle配置連線池中最少空閒maxIdle個連線,用initialSize配置初始化連線數目。可同時配置多個數據源。

如果在Tomcat的server.xml檔案中配置資料來源,有兩種方法都可以實現:

方法1:將上面的配置內容直接新增在<Host>節點下。

方法2:在<GlobalNamingResources>節點下新增:

[html] view plaincopyprint?

  1. <GlobalNamingResources>

  2. <!-- 這裡的factory指的是該Resource 配置使用的是哪個資料來源配置類,這裡使用的是tomcat自帶的標準資料來源Resource配置類,-->

  3. <!-- 這個類也可以自己寫,實現javax.naming.spi.ObjectFactory 介面即可。 -->

  4. <!-- 某些地方使用的commons-dbcp.jar中的org.apache.commons.dbcp.BasicDataSourceFactory,-->

  5. <!-- 如果使用這個就需把commons-dbcp.jar及其依賴的jar包,都放在tomcat的lib下,光放在工程的WEB-INF/lib下是不夠的。  -->

  6.     <Resource

  7.     name="mysql_connect"

  8.     factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"

  9.     maxActive="100"

  10.     maxIdle="30"

  11.     maxWait="10000"

  12.     name="jdbc/TomcatDbPool1"

  13.     password="123456"

  14.     type="javax.sql.DataSource"

  15.     url="jdbc:mysql://localhost:3306/test"

  16.     username="root"/>

  17. </GlobalNamingResources>


然後在context.xml檔案中的<Context></Context>節點中加入如下內容:

[html] view plaincopyprint?

  1. <ResourceLinkname="jdbc/mysql_connect"global="mysql_connect"type="javax.sql.DataSource"/>


在server.xml中配置的資料來源是全域性的,所有專案都可以使用。全域性的resource只是為了重用,方便所有該tomcat下的web工程的資料來源管理,但如果你的tomcat不會同時載入多個web工程,也就是說一個tomcat只加載一個web工程時,是沒有必要配置全域性的resource的。

此外,還需要將mysql的Java驅動類以及其他依賴包(如果有)放到tomcat的lib目錄下。

步驟2:

在web.xml中,配置<resource-ref>元素以在web應用中引用JNDI資源。    

[html] view plaincopyprint?

  1. <resource-ref>

  2.       <!-- 對該資源的描述語言 -->

  3.    <description> dbcpconnect</description>

  4.       <!-- 引用的資源名,必須與Context.xml中的名字一致 -->

  5.    <res-ref-name> jdbc/mysql_connect </res-ref-name>

  6.       <!-- 資源型別 -->

  7.   <res-type>javax.sql.DataSource</res-type>

  8.       <!-- 管理許可權 -->

  9.    <res-auth>Container</res-auth>

  10. </resource-ref>

步驟3:

在Web應用中使用資料來源

[java] view plaincopyprint?

  1. 相關推薦

    Java連線

    http://www.javaweb1024.com/java/JavaWebzhongji/2015/06/01/736.html 對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問題。

    Java常量

    回收 array 數值 編譯期 二進制格式 new 保持 占用 get 轉自:http://www.cnblogs.com/iyangyuan/p/4631696.html jvm虛擬內存分布圖: 程序計數器:JVM執行程序的流水線。 本地方法棧:JVM調用操作系統方法所

    java 常量

    例如 ava color str blog 註意 如果 .cn 運行 參考資料:http://www.cnblogs.com/holos/p/6603379.html 註意: 1.首先,我們平時在討論字符串新建問題時所說的常量池其實指的是全局字符串常量池。並不是運行時常量池

    httpclient架構原理介紹 & 連線

    本篇重點介紹httpclient連線池的相關原理以及介紹,順帶的介紹httpclient傳送請求時的簡單介紹,並會帶上一些原始碼分析。本篇博文是基於httpclient的4.5.2版本進行介紹的。 一、傳送請求的流程原理 幾個關鍵的類和介面介紹 在

    資料庫連線與程式碼實現

    一、資料庫連線池概念        資料庫連線池:負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項技術能明顯提高對資料庫操作的效

    jedis連線(Redis)

    轉自:http://tianxingzhe.blog.51cto.com/3390077/1684306 原子性(atomicity): 一個事務是一個不可分割的最小工作單位,事務中包括的諸操作要麼都做,要麼都不做。 Redis所有單個命令的執行都是原子性的,這與它的單執行緒機制有關; Redis命令

    連線,c3p0與dbcp的區別!

    連線池:    連線池是建立和管理一個連線的緩衝池的技術,這些連線準備好被任何需要它們的執行緒使用。這項技術能明顯提高對資料庫操作的效能。  連線池的好處:(1)對於大多數應用程式,當它們正在處理事務時,僅需要能夠訪問JDBC連線的 1 個執行緒。當不處理事務時,這個連線就會

    spring學習筆記(17)資料庫配置[1]spring資料連線

    資料連線池 在spring中,常使用資料庫連線池來完成對資料庫的連線配置,類似於執行緒池的定義,資料庫連線池就是維護有一定數量資料庫連線的一個緩衝池,一方面,能夠即取即用,免去初始化的時間,另一方面,用完的資料連線會歸還到連線池中,這樣就免去了不必要的連線建立

    Java線程

    最大 rar exception subject alt mod allow 隨著 double 一、線程池初探 所謂線程池,就是將多個線程放在一個池子裏面(所謂池化技術),然後需要線程的時候不是創建一個線程,而是從線程池裏面獲取一個可用的線程,然後執行我們的任務。線程池

    Java高並發之線程

    大小 eight nds 程序退出 zab ron 策略 ace bubuko 線程池優勢 在業務場景中, 如果一個對象創建銷毀開銷比較大, 那麽此時建議池化對象進行管理. 例如線程, jdbc連接等等, 在高並發場景中, 如果可以復用之前銷毀的對象, 那麽系統效率將大大提

    Java中常量

    在Java的記憶體分配中,總共3種常量池: 轉發連結 :https://blog.csdn.net/zm13007310400/article/details/77534349 1.字串常量池(String Constant Pool): 1.1:字串常量池在Java記憶體區域的哪個位

    Java 執行緒

    構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 Java中建立執行緒池很簡單,只需要呼叫Ex

    Java執行緒及例項

    前言 多執行緒的非同步執行方式,雖然能夠最大限度發揮多核計算機的計算能力,但是如果不加控制,反而會對系統造成負擔。執行緒本身也要佔用記憶體空間,大量的執行緒會佔用記憶體資源並且可能會導致Out of Memory。即便沒有這樣的情況,大量的執行緒回收也會給GC帶來很大的壓力

    雜談——Java執行緒

    在一個應用程式中,我們無可避免地需要多次使用執行緒,也就意味著,我們需要多次建立並銷燬執行緒。而建立並銷燬執行緒的過程勢必會消耗記憶體。 舉個例子,假設我們要去爬三百主流媒體網站,每天要抓一次資料,平均每次開銷50毫秒,處理開銷2毫秒,則可以開二十五個執行緒,假設每個網站有十個請求,那麼三百個網

    Tomcat 連線數與執行緒 | BIO/NIO有何不同 | 簡談Kafka中的NIO網路通訊模型

    前言 在使用tomcat時,經常會遇到連線數、執行緒數之類的配置問題,要真正理解這些概念,必須先了解Tomcat的聯結器(Connector)。 在前面的文章 詳解Tomcat配置檔案server.xml 中寫到過:Connector的主要功能,是接收連線請求,建立Req

    Java記憶體分配(堆記憶體、棧記憶體、常量)

      Java程式是執行在JVM(Java虛擬機器)上的,因此Java的記憶體分配是在JVM中進行的,JVM是記憶體分配的基礎和前提。Java程式的執行會涉及以下的記憶體區域: 1. 暫存器:JVM內部虛擬暫存器,存取速度非常快,程式不可控制。 2. 棧:存放

    【搞定Java併發程式設計】第28篇:Java中的執行緒

    上一篇:Java中的併發工具類之執行緒間交換資料的 Exchanger 本文目錄: 1、執行緒池的實現原理  2、執行緒池的使用 2.1、執行緒池的建立 2.2、向執行緒池提交任務 2.3、關閉執行緒池 2.4、合理地配置執行緒池 2.5、執行緒池的監控

    Java併發:執行緒(ThreadPoolExecutor)

    /** * 主池控制狀態ctl是包含兩個概念欄位的原子整數: workerCount:指有效的執行緒數量; * runState:指執行狀態,執行,關閉等。為了將workerCount和runState用1個int來表示, * 我們限制workerCount範圍為(2 ^ 29) - 1,即用int的低

    Java執行緒,看這篇就夠了!

    構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 Java中建立執行緒池很簡單,只需要呼叫Execu

    【本人禿頂程式設計師】Java執行緒,看這篇就夠了!

    ←←←←←←←←←←←← 快!點關注!!! 構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 J