淺析 JNDI / DataSource / ConnectionPool 三者,jndiconnectionpool

來源:互聯網
上載者:User

淺析 JNDI / DataSource / ConnectionPool 三者,jndiconnectionpool

   最近有個使用者量 5W-10W 的 web 應用,頻繁導致 weblogic 崩潰,讓營運組很難受。

   通過幾天跟蹤系統日誌和 weblogic 健全狀態,發現報錯的姿勢有很多,其中對定位問題比較關鍵的報錯:

ExecuteThread: '496' for queue: 'weblogic.kernel.Default (self-tuning)' has beenbusy for "712" seconds working on the request "XXXX", which is more than the configured time (StuckThreadMaxTime) of "600" seconds.

   weblogic 分配給 web 應用使用的線程響應返回周期最大為10分鐘,線程遲遲無法返回結果導致阻塞,並且這樣的刺頭線程越來越多。

   運行一段時間後達到 weblogic 阻塞線程的閥值,weblogic 自然就崩潰了。

   剛開始也試著調大 weblogic 響應周期/阻塞線程的閥值,但是阻塞線程還是會存在並且很快達到閥值。

   仔細比對奔潰前後日誌,查看 weblogic 阻塞線程詳情,導致阻塞開始罪魁禍首是資料庫查詢需要很長時間。

   該系統與內外圍很多廠商系統有進行資料互動,資料庫裡面旁根錯雜的 db_link/synonyms/view/procedure。

   而且是老舊項目,代碼經過很多人修改,已經風燭殘年搖搖欲墜,俺想重造它不是一天兩天了,因為很多原因無法進行,很無奈。

   規範資料庫中的互動流程?然後動代碼?oh,no! 限定解決的期限將至,不能拖。

   所有最後將目光放到資料庫連接池這部分,也使我不得不重新審視這塊對於 Web 專案的重要性。好了,言歸正傳。

1. DataSource / ConnectionPool /  JNDI 三者關係

   

   DataSource:資料來源是在 JDBC2.0 中引入的一個概念;

   在 JDBC 擴充包中定義了Java.sql.DataSource 介面,它負責建立與資料庫的串連;

   在應用程式訪問資料庫是不必編寫串連資料庫的代碼,可直接從資料來源獲得資料庫連接。

   ConnectionPool :在資料來源中初始化建立了多個資料庫連接,這些資料庫連接儲存在串連池(ConnectionPool)中。

   Java程式訪問資料庫時,只需從串連池中取出空閑狀態的資料庫連接,當訪問結束時,將資料庫連接返回給串連池。

   JNDI : (Java Naming and Directory Interface)Java命名與目錄介面;

   為開發人員提供了尋找和訪問各種命名和目錄服務的通用、統一的介面。

   其實可以將 JNDI 理解為一種對象和名字綁定的技術,即指定一個資源名稱,將該名稱與某一資源或服務相關聯。

   結合圖和上面的簡述,資料層關鍵性對象都已展露無遺,同樣也很容易理解。

   JNDI 避免了程式與資料庫之間的緊耦合,使應用更加易於配置、易於部署。

2. 配置 JNDI 資料來源的方式和使用

   weblogic 上配置 JNDI 為圖形介面,操作起來很方便,而且那是營運組的事情,術業有專攻。

   這裡我拿 Tomcat 為例(開發時你也不可能在本機裝個 weblogic 調試吧),簡述下配置 JDNI 的幾種方式:

a. 全域使用:Tomcat 的 conf 檔案夾下的 context.xml  設定檔中添加:

<Resource name="jndi/db_test"               auth="Container"               type="javax.sql.DataSource"               driverClassName="com.mysql.jdbc.Driver"               url="jdbc:mysql://localhost:3306/db_test"               username="root"               password="123456"               maxActive="20"               maxIdle="10"               maxWait="10000"/>      

b.局部使用:Tomcat 的 conf 檔案夾下 server.xml 的 <host> 標籤內添加:

Context path="/demo_jndi" docBase="/demo_jndi">     <Resource       name="jndi/db_test"       type="javax.sql.DataSource"       driverClassName="com.mysql.jdbc.Driver"       maxIdle="2"       maxWait="5000"       username="root"       password="123456"       url="jdbc:mysql://localhost:3306/db_test"       maxActive="4"/>  </Context>  

 c.局部使用:應用 META-INFO 下建立 context.xml 添加:

<?xml version="1.0" encoding="UTF-8"?>  <Context>      <Resource name="jndi/db_test"                   auth="Container"                   type="javax.sql.DataSource"                   driverClassName="com.mysql.jdbc.Driver"                   url="jdbc:mysql://localhost:3306/db_test"                   username="root"                   password="123456"                   maxActive="20"                   maxIdle="10"                   maxWait="10000"/>      </Context>  

   上述幾種配置使用的資料來源都為 javax.sql.DataSource,當然你也可以引入其他開源的資料來源。

   也就是 web 容器使用其他的開來源資料庫串連池,比如像下面這集中姿勢(記得將依賴的 jar 添加到容器的 lib 中):

<Resource name="jndi/db_test"               auth="Container"            //DBCP            type="javax.sql.DataSource"            factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"                    //C3P0            type="com.mchange.v2.c3p0.ComboPooledDataSource"            factory="org.apache.naming.factory.BeanFactory"                           //Druid            type="com.alibaba.druid.pool.DruidDataSource"             factory="com.alibaba.druid.pool.DruidDataSourceFactory"                        driverClassName="com.mysql.jdbc.Driver"               url="jdbc:mysql://localhost:3306/db_test"               username="root"               password="123456"               maxActive="20"               maxIdle="10"               maxWait="10000"/>    

   配置好之後,使用起來也是相當的簡單,核心如下2行代碼即可:

    Context ctx = new InitialContext();      DataSource ds = (DataSource) ctx.lookup("java:comp/env/jndi/db_test");  

   如果項目中引入了 Spring 上述兩行代碼都可以省了,變動注入資料來源配置,如下:

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">          <property name="jndiName" value = "java:comp/env/jndi/db_test"/>      </bean>  
3. 小結

   應用起初使用的是內建 C3P0 ConnectionPool,出現崩潰問題後,輾轉嘗試很多方法。

   將應用的資料庫連接池改動為伺服器 weblogic  JNDI ConnectionPool ,使資料庫連接的壓力從應用轉移到 web 容器。

   崩潰問題得到了緩解,經過後續的 weblogic 串連池參數的調整,卡死崩潰問題得到妥善解決。

   騷年?是不是感覺 web 容器配置 JNDI 提供給應用使用後效率遠遠大於應用內建的串連池。

   同樣 JNDI 避免了程式與資料庫之間的緊耦合,使應用更加易於配置、易於部署。

   試想發布在 weblogic 上面的 10個內建串連池的應用,當資料庫資訊變動時,你是不是想哭?

   而且這樣幾乎無代碼改動,只需變動下 DataSource 的擷取。

 

相關文章

聯繫我們

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

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

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.