Druid是阿里巴巴的一个开源项目,据该网站称:Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
上述内容难免有水分,但是如果真如他所说Druid已经在阿里巴巴和淘宝等大型网站及系统上被充分使用及测试的话,那么Druid还是值得信赖的,毕竟任何有信誉公司不会拿这个去开玩笑。
Druid官网:http://code.alibabatech.com/wiki/display/Druid/Home
Druid有以下几点优势或好处:
- 替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
- 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
- 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。
- SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。
- 扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
看到上面的这些Druid的好处你是否已经心动了?下面就让我们一起来实验一下。
1.下载Druid(http://code.alibabatech.com/mvn/releases/com/alibaba/druid/),目前Druid最新版本为0.2.23,可以选择源码,javadoc,jar等。
2.还是在之前举例的项目基础上添加Druid代码,代码其实很简单,把之前的c3p0改改就能用:
/**
* Druid
*/
public void getUsrInfoWithDruid(Integer usrId) {
String sql="SELECT * FROM USER u WHERE u.USR_ID=" + usrId;
try {
//通过Map方式设置Druid参数
Map<String, String> druidMap=new HashMap<String, String>();
druidMap.put(DruidDataSourceFactory.PROP_USERNAME, user);
druidMap.put(DruidDataSourceFactory.PROP_PASSWORD, passwd);
druidMap.put(DruidDataSourceFactory.PROP_URL, jdbcUrl);
druidMap.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, driver);
//通过DruidDataSourceFactory获取DataSource实例
dataSource=DruidDataSourceFactory.createDataSource(druidMap);
conn=dataSource.getConnection();
Statement st=conn.createStatement();
ResultSet result=st.executeQuery(sql);
while(result.next()) {
System.out.println("Druid:begin");
System.out.println("Name:" + result.getString("NAME"));
System.out.println("Druid:end");
}
result.close();
st.close();
conn.close();
} catch(Exception e) {
e.printStackTrace();
}
}
以上是利用Map方式向Druid传递参数,这种方式基本上用不到。
3.利用属性文件传递参数:
#MySQL驱动 druid.driverClassName=com.mysql.jdbc.Driver #MySQL连接地址 druid.url=jdbc\:mysql\://192.168.0.8\:3306/test #数据库用户 druid.username=moster #该用户密码 druid.password=shzygjrmdwg #自动提交 druid.defaultAutoCommit=false #只读设置 druid.defaultReadOnly=false druid.defaultTransactionIsolation= druid.defaultCatalog= #连接池最大使用连接数量 druid.maxActive=25 #连接池最大空闲 druid.maxIdle=25 #连接池最小空闲 druid.minIdle=1 #初始化连接池大小 druid.initialSize=1 #连接等待时间,默认:-1 druid.maxWait=3000 druid.testOnBorrow= druid.testOnReturn= #检测间隔,检测需要关闭的空闲连接,单位:毫秒 druid.timeBetweenEvictionRunsMillis= druid.numTestsPerEvictionRun= #一个连接在池中最小生存的时间,单位:毫秒 druid.minEvictableIdleTimeMillis= druid.testWhileIdle= #测试SQL druid.validationQuery= #测试超时时间 druid.validationQueryTimeout= #初始化连接SQL druid.initConnectionSqls= druid.accessToUnderlyingConnectionAllowed= #移除被废弃连接 druid.removeAbandoned= #超时时间 druid.removeAbandonedTimeout= #日志记录 druid.logAbandoned= #PreparedStatements druid.poolPreparedStatements= #PreparedStatement最大数量 druid.maxOpenPreparedStatements= #属性配置文件 druid.connectionProperties= #filters配置 druid.filters= #Exception处理 druid.exceptionSorter= #Exception处理类名 druid.exception-sorter-class-name= #初始化 druid.init=
官网居然连这些属性的解释都没有,以上是我自己翻译的,如有偏差请及时指正。
4.将原创建DataSource方法修改为:
Properties p=new Properties();
p.load(getClass().getResourceAsStream("/druid.properties"));
//通过属性文件设置Druid参数
dataSource=DruidDataSourceFactory.createDataSource(p);
Druid的参数可以参考DruidDataSourceFactory类的源码,其中参数的命名规则与c3p0,DBCP非常像,也比较容易理解,以下是具体参数:
String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
String PROP_DEFAULTREADONLY = "defaultReadOnly";
String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
String PROP_DEFAULTCATALOG = "defaultCatalog";
String PROP_DRIVERCLASSNAME = "driverClassName";
String PROP_MAXACTIVE = "maxActive";
String PROP_MAXIDLE = "maxIdle";
String PROP_MINIDLE = "minIdle";
String PROP_INITIALSIZE = "initialSize";
String PROP_MAXWAIT = "maxWait";
String PROP_TESTONBORROW = "testOnBorrow";
String PROP_TESTONRETURN = "testOnReturn";
String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
String PROP_TESTWHILEIDLE = "testWhileIdle";
String PROP_PASSWORD = "password";
String PROP_URL = "url";
String PROP_USERNAME = "username";
String PROP_VALIDATIONQUERY = "validationQuery";
String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";
String PROP_INITCONNECTIONSQLS = "initConnectionSqls";
String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
String PROP_REMOVEABANDONED = "removeAbandoned";
String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
String PROP_LOGABANDONED = "logAbandoned";
String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
String PROP_CONNECTIONPROPERTIES = "connectionProperties";
String PROP_FILTERS = "filters";
String PROP_EXCEPTION_SORTER = "exceptionSorter";
String PROP_EXCEPTION_SORTER_CLASS_NAME = "exception-sorter-class-name";
String PROP_INIT = "init";
Druid监控:
同Proxool一样Druid也提供了监控功能,而且更强大!
Druid的监控配置起来跟Proxool类似,其实我的感觉就是Druid把现在主流的连接池优点结合起来了,很有中国人做东西的“风格”。
<!-- Druid监控Servlet --> <servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/druid/*</url-pattern> </servlet-mapping>
打开浏览器就可以看到监控页面了。
下图是Druid官网给出的几种连接池的对比表格,从数据上来看Druid在各方面都占有很大的优势,实际情况还需要实践去检验。
LRU
LRU是一个性能关键指标,特别Oracle,每个Connection对应数据库端的一个进程,如果数据库连接池遵从LRU,有助于数据库服务器优化,这是重要的指标。在测试中,Druid、DBCP、Proxool、JBoss是遵守LRU的。BoneCP、C3P0则不是。BoneCP在mock环境下性能可能好,但在真实环境中则就不好了。
PSCache
PSCache是数据库连接池的关键指标。在Oracle中,类似SELECT NAME FROM USER WHERE ID = ?这样的SQL,启用PSCache和不启用PSCache的性能可能是相差一个数量级的。Proxool是不支持PSCache的数据库连接池,如果你使用Oracle、SQL Server、DB2、Sybase这样支持游标的数据库,那你就完全不用考虑Proxool。
PSCache-Oracle-Optimized
Oracle 10系列的Driver,如果开启PSCache,会占用大量的内存,必须做特别的处理,启用内部的EnterImplicitCache等方法优化才能够减少内存的占用。这个功能只有DruidDataSource有。如果你使用的是Oracle Jdbc,你应该毫不犹豫采用DruidDataSource。
ExceptionSorter
ExceptionSorter是一个很重要的容错特性,如果一个连接产生了一个不可恢复的错误,必须立刻从连接池中去掉,否则会连续产生大量错误。这个特性,目前只有JBossDataSource和Druid实现。Druid的实现参考自JBossDataSource。
监控
DruidDataSource自身提供有NotEmptyWaitCount、PSCahcheHitCount等有用的监控属性,通过配置StatFilter能够监控SQL的执行情况。
扩展
DruidDataSource提供基于Filter-Chain模式的模式的扩展。