隨筆-17  評論-64  文章-79  trackbacks-1
          配置Tomcat?4.1.29的連接池
          Tomcat?4.1.29是目前的最高穩定版本,下面介紹一下它的連接池配置方法。
          1)????連接池配置(Database?Connection?Pool?(DBCP)?Configurations)
          DBCP使用的是Jakarta-Commons?Database?Connection?Pool?要使用連接池需要如下的組件即jar文件。
          Jakarta-Commons?DBCP?1.1?對應commons-dbcp-1.1.jar。
          Jakarta-Commons?Collections?2.0?對應commons-collections.jar。
          Jakarta-Commons?Pool?1.1?對應commons-pool-1.1.jar。
          這三個jar文件要與你的JDBC驅動程序一起放到【TOMCAT_HOME】\common\lib目錄下以便讓tomcat和你的web應用都能夠找到。
          注:這三個jar文件是默認存在與【TOMCAT_HOME】\common\lib下的。
          需要注意的地方:第三方的驅動程序或者其他類只能以*.jar的形式放到Tomcat的common\lib目錄中,因為Tomcat只把*.jar文件加到CLASSPATH中。
          不要把上訴三個文件放到WEB-INF/lib或者其他地方因為這樣會引起混淆。

          2)????通過配置阻止連接池漏洞
          數據庫連接池創建和管理連接池中建立好的數據庫連接,循環使用這些連接以得到更好的效率。這樣比始終為一個用戶保持一個連接和為用戶的請求頻繁的建立和銷毀數據庫連接要高效的多。
          這樣就有一個問題出現了,一個Web應用程序必須顯示的釋放ResultSet,Statement和Connection。如果在關閉這些資源的過程中失敗將導致這些資源永遠不在可用,這就是所謂的連接池漏洞。這個漏洞最終會導致連接池中所有的連接不可用。
          通過配置Jakarta?Common?DBCP可以跟蹤和恢復那些被遺棄的數據庫連接。
          以下是一系列相關配置:
          ?????通過配置DBCP數據源中的參數removeAbandoned來保證刪除被遺棄的連接使其可以被重新利用。
          為ResourceParams(見下文的數據源配置)標簽添加參數removeAbandoned
          <parameter>
          <name>removeAbandoned</name>
          <value>true</value>
          </parameter>
          通過這樣配置的以后當連接池中的有效連接接近用完時DBCP將試圖恢復和重用被遺棄的連接。這個參數的值默認是false。
          ?????通過設置removeAbandonedTimeout來設置被遺棄的連接的超時的時間,即當一個連接連接被遺棄的時間超過設置的時間時那么它會自動轉換成可利用的連接。
          ????<parameter>
          ?????<name>removeAbandonedTimeout</name>
          ?????<value>60</value>
          ?????</parameter>
          ????默認的超時時間是300秒。
          ?????設置logAbandoned參數,這個參數的用處我沒能夠理解它的意義所以提供原文供大家參考。
          The?logAbandoned?parameter?can?be?set?to?true?if?you?want?DBCP?to?log?a?stack?trace?of?the?code?which?abandoned?the?dB?connection?resources。
          <parameter>
          <name>logAbandoned</name>
          <value>true</value>
          </parameter>
          這個參數默認為false。

          3)????下面以MySQL為例演示Tomcat數據庫連接池的配置
          ?????MySQL的版本以及對應的JDBC驅動程序
          MySQL?3.23.47,?MySQL?3.23.47?using?InnoDB,?MySQL?4.0.1alpha對應的驅動為mm.mysql?2.0.14?(JDBC?Driver)。
          ?????在MySQL中創建供測試的數據庫,表結構以及數據
          mysql>?create?database?javatest;
          mysql>?use?javatest;
          mysql>?create?table?testdata?(
          ????->???id?int?not?null?auto_increment?primary?key,
          ????->???foo?varchar(25),?
          ????->???bar?int);
          ????mysql>?insert?into?testdata?values(null,?'hello',?12345);
          Query?OK,?1?row?affected?(0.00?sec)

          mysql>?select?*?from?testdata;
          +----+-------+-------+
          |?ID?|?FOO???|?BAR???|
          +----+-------+-------+
          |??1?|?hello?|?12345?|
          +----+-------+-------+
          1?row?in?set?(0.00?sec)


          ????要注意的是登錄的mysql用戶要有創建數據庫的權限還有注意要設置密碼我用的是root^_^。
          ?????配置Tomcat的server.xml文件
          配置【TOMCAT_HOME】\common\lib下的server.xml文件,在</host>標簽之前加入以下內容以添加JNDI數據源:
          <Context?path="/DBTest"?docBase="DBTest"
          ????????debug="5"?reloadable="true"?crossContext="true">
          ??<Logger?className="org.apache.catalina.logger.FileLogger"
          ?????????????prefix="localhost_DBTest_log."?suffix=".txt"
          ?????????????timestamp="true"/>
          ??<Resource?name="jdbc/TestDB"
          ???????????????auth="Container"
          ???????????????type="javax.sql.DataSource"/>
          ??<ResourceParams?name="jdbc/TestDB">
          ????<parameter>
          ??????<name>factory</name>
          ????<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
          ????</parameter>
          ????<!--?Maximum?number?of?dB?connections?in?pool.?Make?sure?you
          ?????????configure?your?mysqld?max_connections?large?enough?to?handle
          ?????????all?of?your?db?connections.?Set?to?0?for?no?limit.
          ?????????-->
          ????<parameter>
          ??????<name>maxActive</name>
          ??????<value>100</value>
          ????</parameter>
          ????<!--?Maximum?number?of?idle?dB?connections?to?retain?in?pool.
          ?????????Set?to?0?for?no?limit.
          ?????????-->
          ????<parameter>
          ??????<name>maxIdle</name>
          ??????<value>30</value>
          ????</parameter>
          ????<!--?Maximum?time?to?wait?for?a?dB?connection?to?become?available
          ?????????in?ms,?in?this?example?10?seconds.?An?Exception?is?thrown?if
          ?????????this?timeout?is?exceeded.??Set?to?-1?to?wait?indefinitely.
          ?????????-->
          ????<parameter>
          ??????<name>maxWait</name>
          ??????<value>10000</value>
          ????</parameter>
          ????<!--?MySQL?dB?username?and?password?for?dB?connections??-->
          ????<parameter>
          ?????<name>username</name>
          ?????<value>javauser</value>
          ????</parameter>
          ????<parameter>
          ?????<name>password</name>
          ?????<value>javadude</value>
          ????</parameter>
          ????<!--?Class?name?for?mm.mysql?JDBC?driver?-->
          ????<parameter>
          ???????<name>driverClassName</name>
          ???????<value>org.gjt.mm.mysql.Driver</value>
          ????</parameter>
          ????<!--?The?JDBC?connection?url?for?connecting?to?your?MySQL?dB.
          ?????????The?autoReconnect=true?argument?to?the?url?makes?sure?that?the
          ?????????mm.mysql?JDBC?Driver?will?automatically?reconnect?if?mysqld?closed?the
          ?????????connection.??mysqld?by?default?closes?idle?connections?after?8?hours.
          ?????????-->
          ????<parameter>
          ??????<name>url</name>?<value>jdbc:mysql://localhost:3306/javatest?autoReconnect=true</value>
          ????</parameter>
          ??</ResourceParams>
          </Context>
          ?????配置Web應用程序的web.xml文件
          <?xml?version="1.0"?encoding="ISO-8859-1"?>
          ????<!DOCTYPE?web-app?PUBLIC
          ????"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"
          ????"http://java.sun.com/dtd/web-app_2_3.dtd">
          <web-app>
          ??<description>MySQL?Test?App</description>
          ??<resource-ref>
          ??????<description>DB?Connection</description>
          ??????<res-ref-name>jdbc/TestDB</res-ref-name>
          ??????<res-type>javax.sql.DataSource</res-type>
          ??????<res-auth>Container</res-auth>
          ??</resource-ref>
          </web-app>

          ?????測試代碼
          測試代碼包括一個JSP文件和一個Java類。代碼如下:
          1. <html>
          2. ??<head>
          3. ????<title>DB?Test</title>
          4. ??</head>
          5. ??<body>
          6. ??<%
          7. ????foo.DBTest?tst?=?new?foo.DBTest();
          8. ????tst.init();
          9. ??%>
          10. ??<h2>Results</h2>
          11. ????Foo?<%=?tst.getFoo()?%><br>
          12. ????Bar?<%=?tst.getBar()?%>
          13. ??</body>
          14. </html>
          15. package?foo;
          16. import?javax.naming.*;
          17. import?javax.sql.*;
          18. import?java.sql.*;
          19. public?class?DBTest?{
          20. ??String?foo?=?"Not?Connected";
          21. ??int?bar?=?-1;
          22. ????
          23. ??public?void?init()?{
          24. ????try{
          25. ??????Context?ctx?=?new?InitialContext();
          26. ??????if(ctx?==?null?)?
          27. ??????????throw?new?Exception("Boom?-?No?Context");
          28. ??????DataSource?ds?=?
          29. ????????????(DataSource)ctx.lookup(
          30. ???????????????"java:comp/env/jdbc/TestDB");
          31. ??????if?(ds?!=?null)?{
          32. ????????Connection?conn?=?ds.getConnection();?????
          33. ????????if(conn?!=?null)??{
          34. ????????????foo?=?"Got?Connection?"+conn.toString();
          35. ????????????Statement?stmt?=?conn.createStatement();
          36. ????????????ResultSet?rst?=?
          37. ????????????????stmt.executeQuery(
          38. ??????????????????"select?id,?foo,?bar?from?testdata");
          39. ????????????if(rst.next())?{
          40. ???????????????foo=rst.getString(2);
          41. ???????????????bar=rst.getInt(3);
          42. ????????????}
          43. ????????????conn.close();
          44. ????????}
          45. ??????}
          46. ????}catch(Exception?e)?{
          47. ??????e.printStackTrace();
          48. ????}
          49. ?}
          50. ?public?String?getFoo()?{?return?foo;?}
          51. ?public?int?getBar()?{?return?bar;}
          52. }

          最后在Tomcat的webapps目錄下建立DBTest然后將應用程序文件拷貝到這個目錄下即可。
          ?????重新啟動Tomcat在瀏覽器上http://localhost:8080/DBTest/test.jsp即可看到結果。
          Results
          Foo?hello
          Bar?12345

          4)????一些常見的問題
          ?????由于垃圾收集器的運行而導致連接超時
          Tomcat是運行在JVM中的,JVM要周期性的執行GC(垃圾收集器)來清除不再被引用的Java對象。在GC運行時Tomcat將會凍結,如果在設置連接池中的連接的最大等待時間(MaxWait)小于GC的運行時間的話那么你很可能在使用數據庫連接時失敗。推薦將連接的超時時間設置成10到15秒。
          注意連接的超時時間與被遺棄的連接的超時時間的區別。
          ?????重復關閉連接引發的異常
          這種情況發生在當響應一個客戶的請求時從數據庫連接池里取得了連接但是關閉了兩次。使用連接池中的連接與使用直接與數據庫建立的連接是不一樣的,連接池中的連接在釋放時只是將連接返回到連接池而不是釋放連接的資源。Tomcat使用多線程來處理并發的請求,以下實例演示了一個在Tomcat中可以導致出錯的過程:
          請求A在線程A中運行并從連接池中得到一個連接
          請求A關閉了這個連接
          JVM轉到線程B
          請求B在線程B中運行并取得一個連接(這個連接是請求A剛剛返回的那個)
          JVM轉到線程A
          請求A在finally塊中又一次關閉連接(因為第一次沒有設置連接引用為null)
          JVM轉到線程B
          請求B試圖使用得到的連接但連接已經被請求A返回到了連接池中所以請求B的操作失敗
          以下是一段公認的恰當的代碼可以避免以上的問題
          1. ??Connection?conn?=?null;
          2. ??Statement?stmt?=?null;??//?Or?PreparedStatement?if?needed
          3. ??ResultSet?rs?=?null;
          4. ??try?{
          5. ????conn?=?...?get?connection?from?connection?pool?...
          6. ????stmt?=?conn.createStatement("select?...");
          7. ????rs?=?stmt.executeQuery();
          8. ????...?iterate?through?the?result?set?...
          9. ????rs.close();
          10. ????rs?=?null;
          11. ????stmt.close();
          12. ????stmt?=?null;
          13. ????conn.close();?//?Return?to?connection?pool
          14. ????conn?=?null;??//?Make?sure?we?don't?close?it?twice
          15. ??}?catch?(SQLException?e)?{
          16. ????...?deal?with?errors?...
          17. ??}?finally?{
          18. ????//?Always?make?sure?result?sets?and?statements?are?closed,
          19. ????//?and?the?connection?is?returned?to?the?pool
          20. ????if?(rs?!=?null)?{
          21. ??????try?{?rs.close();?}?catch?(SQLException?e)?{?;?}
          22. ??????rs?=?null;
          23. ????}
          24. ????if?(stmt?!=?null)?{
          25. ??????try?{?stmt.close();?}?catch?(SQLException?e)?{?;?}
          26. ??????stmt?=?null;
          27. ????}
          28. ????if?(conn?!=?null)?{
          29. ??????try?{?conn.close();?}?catch?(SQLException?e)?{?;?}
          30. ??????conn?=?null;
          31. ????}
          32. ??}
          posted on 2006-05-18 13:45 飛鳥 閱讀(587) 評論(0)  編輯  收藏 所屬分類: JSP

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 潜山县| 大关县| 大新县| 福海县| 饶河县| 长宁区| 元谋县| 梁平县| 娄烦县| 闸北区| 兴国县| 西宁市| 利津县| 屯昌县| 赫章县| 金平| 灵台县| 磐安县| 大英县| 华蓥市| 多伦县| 乐亭县| 南部县| 贡觉县| 新蔡县| 五华县| 贵溪市| 石楼县| 咸阳市| 平顺县| 阳西县| 大新县| 吴忠市| 铜川市| 辽源市| 额敏县| 木兰县| 开封县| 新晃| 肥东县| 昭觉县|