JNDI與JDBC比較以及鏈接池的技術

       Java Database Connectivity(JDBC)JDBC 以一種統一的方式來對各類各樣的數據庫進行存取。和 ODBC 同樣, JDBC 爲開發人員隱藏了不一樣數據庫的不一樣特性。另外,因爲 JDBC 創建在 Java 的基礎上 , 所以還提供了數據庫存取的平臺獨立性。 JDBC 定義了 4 種不一樣的驅動程序: JDBC-ODBCBridge JDBC-native driverbridge JDBC-networkbridge PureJavadriver 。在一個多層的企業級應用中,更大的多是在客戶端和一個 EJB 進行通訊,採用 EJB 創建數據庫鏈接。爲了實現和改進可伸縮性和系統性能, 也能夠採用鏈接緩衝池( connection pool )優化數據庫鏈接。

Java Naming and Directory Interface (JNDI)JNDI API被用於執行名字和目錄服務。它提供了一致的模型來存取和操做企業級的資源如DNSLDAP,本地文件系統,後者在應用服務器中的對象。在JNDI中,在目錄結構中的每個結點稱爲context。每個JNDI名字都是相對於context的。應用能夠經過這個初始化的context經有這個目錄樹來定位它所須要的資源或對象。 java

JNDI相對與JDBC來講是他的靈活性,程序員不須要關心「具體的數據庫後臺是什麼?JDBC驅動程序是什麼?JDBC URL格式是什麼?訪問數據庫的用戶名和口令是什麼?」等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或鏈接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只須要對這些配置和管理進行引用便可。 程序員

理解鏈接池 sql

鏈接池是建立和管理多個鏈接的一種技術,這些鏈接可被須要使用它們的任何線程使用。鏈接池技術基於下述事實:對於大多數應用程序,當它們正在處理一般須要數毫秒完成的事務時,僅須要可以訪問JDBC鏈接的1個線程。未處理事務時,鏈接處於閒置狀態。使用鏈接池,容許其餘線程使用閒置鏈接來執行有用的任務。 數據庫

事實上,當某一線程須要用JDBCMySQL或其餘數據庫上執行操做時,須要用到由鏈接池提供的鏈接。使用鏈接完成線程後,線程會將鏈接返回給鏈接池,以便該鏈接可以被其餘須要使用鏈接的線程使用。 編程

從鏈接池「借出」鏈接時,該鏈接僅供請求它的線程使用。從編程觀點看,其效果等同於每次須要JDBC鏈接時調用DriverManager.getConnection(),可是,採用鏈接池技術,可經過使用新的或已有的鏈接結束線程。 服務器

鏈接池技術能顯著增長Java應用程序的性能,同時還能下降資源使用率。鏈接池技術的主要優勢包括: 併發

·         縮短了鏈接建立時間 app

與其餘數據庫相比,MySQL提供了快速的鏈接設置功能,鏈接時間一般不是問題,但建立新的JDBC鏈接仍會致使聯網操做和必定的IDBC驅動開銷,若是這類鏈接是「循環」使用的,使用該方式,可避免這類不利因素。 ide

·         簡化的編程模型 工具

使用鏈接池技術時,每一個單獨線程可以像建立了本身的JDBC鏈接那樣進行操做,從而容許使用直接的JDBC編程技術。

·         受控的資源使用

若是不使用鏈接池技術,而是在每次須要時爲線程建立新的鏈接,那麼應用程序的資源使用將十分浪費,並且在負載較重的狀況下會致使沒法預期的結果。

注意,與MySQL的每一個鏈接均會在客戶端和服務器端形成必定的開銷(每寸、CPU、關聯轉換等)。每一個鏈接均會對應用程序和MySQL服務器的可用資源帶來必定的限制。不管鏈接是否執行任何有用的任務,仍將使用這些資源中的至關一部分。

鏈接池可以使性能最大化,同時還能將資源利用控制在必定的水平之下,若是超過該水平,應用程序將崩潰而不只僅是變慢。

幸運的是,Sun公司經過JDBC-2.0「可選」接口,完成了JDBC中鏈接池概念的標準化實施,全部主要應用服務器均實施了可以與MySQL Connector/J一塊兒良好工做的這類API

一般,你能夠在應用服務器的配置文件中配置鏈接池,並經過Java命名和目錄接口(JNDI)訪問它。在下面的代碼中,介紹了在J2E應用服務器上運行的應用程序中使用鏈接池的方法:

示例26.12. J2EE應用服務器一塊兒使用鏈接池

import java.sql.Connection;

import java.sql.SQLException;

import java.sql.Statement;

import javax.naming.InitialContext;

import javax.sql.DataSource;

public class MyServletJspOrEjb {

    public void doSomething() throws Exception {

        /*

         * Create a JNDI Initial context to be able to

         * lookup the DataSource

         *

         * In production-level code, this should be cached as

         * an instance or static variable, as it can

         * be quite expensive to create a JNDI context.

         *

         * Note: This code only works when you are using servlets

         * or EJBs in a J2EE application server. If you are

         * using connection pooling in standalone Java code, you

         * will have to create/configure datasources using whatever

         * mechanisms your particular connection pooling library

         * provides.

         */

        InitialContext ctx = new InitialContext();

         /*

          * Lookup the DataSource, which will be backed by a pool

          * that the application server provides. DataSource instances

          * are also a good candidate for caching as an instance

          * variable, as JNDI lookups can be expensive as well.

          */

        DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");

        /*

         * The following code is what would actually be in your

         * Servlet, JSP or EJB 'service' method...where you need

         * to work with a JDBC connection.

         */

        Connection conn = null;

        Statement stmt = null;

        try {

            conn = ds.getConnection();

            /*

             * Now, use normal JDBC programming to work with

             * MySQL, making sure to close each resource when you're

             * finished with it, which allows the connection pool

             * resources to be recovered as quickly as possible

             */

            stmt = conn.createStatement();

            stmt.execute("SOME SQL QUERY");

            stmt.close();

            stmt = null;

            conn.close();

            conn = null;

        } finally {

            /*

             * close any jdbc instances here that weren't

             * explicitly closed during normal code path, so

             * that we don't 'leak' resources...

             */

            if (stmt != null) {

                try {

                    stmt.close();

                } catch (sqlexception sqlex) {

                    // ignore -- as we can't do anything about it here

                }

                stmt = null;

            }

            if (conn != null) {

                try {

                    conn.close();

                } catch (sqlexception sqlex) {

                    // ignore -- as we can't do anything about it here

                }

                conn = null;

            }

        }

    }

}

如上例所示,得到JNDI InitialContext並查找到數據庫後,其他代碼與過去在JDBC編程中使用的相似。

使用鏈接池時須要牢記的最重要事項是,不管在代碼中出現了什麼(異常、控制流等),鏈接以及由鏈接建立的任何部分(語句、結果集等)均應被關閉,以便能再次使用它們。如否則,它們將糾纏在一塊兒,在最好的狀況下,意味着它們所表明的MySQL服務器資源(緩衝區、鎖定、套接字等)可能會捆綁一段時間,在最壞的狀況下,可能會致使永久捆綁。

鏈接池的最佳大小是什麼?

與全部其餘配置經驗規則同樣,回答是「它取決於具體狀況」。儘管最佳大小取決與預期的負載和平均的數據庫事務時間,最佳的鏈接池大小小於你的預期。例如,若是使用的是Sun公司的Java Petstore Blueprint應用程序,對於包含1520個鏈接的鏈接池,使用MySQLTomcat,在可接受的相應時間下,可服務於中等程度的負載(600個併發用戶)。

要想肯定用於應用程序的鏈接池大小,應使用諸如Apache JmeterThe Grinder等工具建立負載測試腳本,並對應用程序進行負載測試。

肯定出發點的一種簡單方法是,將鏈接池的最大鏈接數配置爲「無限」,運行負載測試,並測量最大的併發鏈接數。隨後,應進行反向操做,肯定出使應用程序具備最佳性能的鏈接池的最小和最大值。

相關文章
相關標籤/搜索