使用 Tomcat 7 新的鏈接池 —— Tomcat jdbc pool

Tomcat 在 7.0 之前的版本都是使用 commons-dbcp 作爲鏈接池的實現,可是 dbcp 飽受詬病,緣由有:java

  • dbcp 是單線程的,爲了保證線程安全會鎖整個鏈接池
  • dbcp 性能不佳
  • dbcp 太複雜,超過 60 個類
  • dbcp 使用靜態接口,在 JDK 1.6 編譯有問題
  • dbcp 發展滯後
  • 所以不少人會選擇一些第三方的鏈接池組件,例如 c3p0 , bonecp, druid 等。

爲此,Tomcat 從 7.0 開始引入一個新的模塊:Tomcat jdbc poolmysql

  • tomcat jdbc pool 近乎兼容 dbcp ,性能更高
  • 異步方式獲取鏈接
  • tomcat jdbc pool 是 tomcat 的一個模塊,基於 tomcat JULI,使用 Tomcat 的日誌框架
  • 使用 javax.sql.PooledConnection 接口獲取鏈接
  • 支持高併發應用環境
  • 超簡單,核心文件只有8個,比 c3p0 還
  • 更好的空閒鏈接處理機制
  • 支持 JMX
  • 支持 XA Connection
  • tomcat jdbc pool 的優勢遠不止這些,詳情請看這裏。

tomcat jdbc pool 可在 Tomcat 中直接使用,也能夠在獨立的應用中使用。sql

Tomcat 中直接使用的方法:apache

數據源配置:tomcat

<Resource name="jdbc/TestDB"
  auth="Container"
  type="javax.sql.DataSource"
  factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
  testWhileIdle="true"
  testOnBorrow="true"
  testOnReturn="false"
  validationQuery="SELECT 1"
  validationInterval="30000"
  timeBetweenEvictionRunsMillis="30000"
  maxActive="100"
  minIdle="10"
  maxWait="10000"
  initialSize="10"
  removeAbandonedTimeout="60"
  removeAbandoned="true"
  logAbandoned="true"
  minEvictableIdleTimeMillis="30000"
  jmxEnabled="true"
  jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
  username="root"
  password="password"
  driverClassName="com.mysql.jdbc.Driver"
  url="jdbc:mysql://localhost:3306/mysql"/>

異步獲取鏈接的方法:安全

Connection con = null;
try {
    Future < Connection > future = datasource.getConnectionAsync();
    while(!future.isDone()) {
        System.out.println("Connection is not yet available. Do some background work");
        try {
            Thread.sleep(100); //simulate work       
        }catch (InterruptedException x) {    
            Thread.currentThread().interrupted();       
        }   
    }   
    con = future.get(); //should return instantly   
    Statement st = con.createStatement();   
    ResultSet rs = st.executeQuery("select * from user");

在獨立的應用中使用:併發

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
public class SimplePOJOExample {
    public static void main(String[] args) throws Exception {
        PoolProperties p = new PoolProperties();
        p.setUrl("jdbc:mysql://localhost:3306/mysql");
        p.setDriverClassName("com.mysql.jdbc.Driver");
        p.setUsername("root");
        p.setPassword("password");
        p.setJmxEnabled(true);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(true);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(30000);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMaxActive(100);
        p.setInitialSize(10);
        p.setMaxWait(10000);
        p.setRemoveAbandonedTimeout(60);
        p.setMinEvictableIdleTimeMillis(30000);
        p.setMinIdle(10);
        p.setLogAbandoned(true);
        p.setRemoveAbandoned(true);
        p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;" + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
        DataSource datasource = new DataSource();
        datasource.setPoolProperties(p);
        Connection con = null;
        try {
            con = datasource.getConnection();
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery("select * from user");
            int cnt = 1;
            while(rs.next()) {
                System.out.println((cnt++) + ". Host:" + rs.getString("Host") + " User:" + rs.getString("User") + " Password:" + rs.getString("Password"));
            }
            rs.close();
            st.close();
        } finally {
            if(con != null) try {
                con.close();
            } catch(Exception ignore) {}
        }
    }
}
相關文章
相關標籤/搜索