Druid是阿里巴巴的一个开源项目,据该网站称:Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
上述内容难免有水分,但是如果真如他所说Druid已经在阿里巴巴和淘宝等大型网站及系统上被充分使用及测试的话,那么Druid还是值得信赖的,毕竟任何有信誉公司不会拿这个去开玩笑。
Druid官网:http://code./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./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
- druiddruid.defaultTransactionIsolation=
- druid.defaultCatalog=
- #连接池最大使用连接数量
- druid.maxActive=25
- #连接池最大空闲
- druid.maxIdle=25
- #连接池最小空闲
- druid.minIdle=1
- #初始化连接池大小
- druid.initialSize=1
- #连接等待时间,默认:-1
- druid.maxWait=3000
- druiddruid.testOnBorrow=
- druid.testOnReturn=
- #检测间隔,检测需要关闭的空闲连接,单位:毫秒
- druiddruid.timeBetweenEvictionRunsMillis=
- druid.numTestsPerEvictionRun=
- #一个连接在池中最小生存的时间,单位:毫秒
- druiddruid.minEvictableIdleTimeMillis=
- druid.testWhileIdle=
- #测试SQL
- druid.validationQuery=
- #测试超时时间
- druid.validationQueryTimeout=
- #初始化连接SQL
- druiddruid.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模式的模式的扩展。
|