Java Naming and Directory Interface (JNDI)JNDI API被用於執行名字和目錄服務。它提供了一致的模型來存取和操做企業級的資源如DNS和LDAP,本地文件系統,後者在應用服務器中的對象。在JNDI中,在目錄結構中的每個結點稱爲context。每個JNDI名字都是相對於context的。應用能夠經過這個初始化的context經有這個目錄樹來定位它所須要的資源或對象。 java
JNDI相對與JDBC來講是他的靈活性,程序員不須要關心「具體的數據庫後臺是什麼?JDBC驅動程序是什麼?JDBC URL格式是什麼?訪問數據庫的用戶名和口令是什麼?」等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或鏈接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只須要對這些配置和管理進行引用便可。 程序員
理解鏈接池 sql
鏈接池是建立和管理多個鏈接的一種技術,這些鏈接可被須要使用它們的任何線程使用。鏈接池技術基於下述事實:對於大多數應用程序,當它們正在處理一般須要數毫秒完成的事務時,僅須要可以訪問JDBC鏈接的1個線程。未處理事務時,鏈接處於閒置狀態。使用鏈接池,容許其餘線程使用閒置鏈接來執行有用的任務。 數據庫
事實上,當某一線程須要用JDBC在MySQL或其餘數據庫上執行操做時,須要用到由鏈接池提供的鏈接。使用鏈接完成線程後,線程會將鏈接返回給鏈接池,以便該鏈接可以被其餘須要使用鏈接的線程使用。 編程
從鏈接池「借出」鏈接時,該鏈接僅供請求它的線程使用。從編程觀點看,其效果等同於每次須要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應用程序,對於包含15~20個鏈接的鏈接池,使用MySQL和Tomcat,在可接受的相應時間下,可服務於中等程度的負載(600個併發用戶)。
要想肯定用於應用程序的鏈接池大小,應使用諸如Apache Jmeter或The Grinder等工具建立負載測試腳本,並對應用程序進行負載測試。
肯定出發點的一種簡單方法是,將鏈接池的最大鏈接數配置爲「無限」,運行負載測試,並測量最大的併發鏈接數。隨後,應進行反向操做,肯定出使應用程序具備最佳性能的鏈接池的最小和最大值。