??xml version="1.0" encoding="utf-8" standalone="yes"?> 最q的一个项目在Hibernate使用C3P0的连接池Q数据库为Mysql。开发测试没有问题,在运行中每个一D长的空闲时间就出现异常: 查看?jin)Mysql的文档,以及(qing)Connector/J的文档以?qing)在U说明发玎ͼ出现q种异常的原因是Q?/p>
Mysql服务器默认的“wait_timeout”?时Q也是说一个connectionI闲过8个小ӞMysql自动断开该connection。这是问题的所在,在C3P0 pools中的connections如果I闲过8时QMysql其断开Q而C3P0q不知道该connection已经失效Q如果这时有ClienthconnectionQC3P0该失效的Connection提供lC(j)lientQ将?x)造成上面的异常?/p>
解决的方法有3U:(x) 当然最好的办法是同时综合用上q?U方法,下面DBCP和C3P0分别做一说明Q假设wait_timeout为默认的8时 DBCP增加以下配置信息:
*2007-8-15
*转蝲h明出处及(qing)作?
*/
前两天在看Spring内置的拦截器的时候,发现?jin)一个之前没有注意的c:(x)org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptorQ好奇心(j)?j)我上|查?jin)一下这个jamon。大概看?jin)一下之后发现这个玩意还真挺好用的而且挺重要的Q而且现在国内对它的介l也很少Q所以写?jin)一文章和大家分n?
一QJamon介:(x)
Jamon的全名是QJava Application Monitor。它是一个小巧的Q免费的Q高性能的,U程安全的性能监测工具。它可以用来定pȝ的性能瓉Q也可以用来监视用户和应用程序之间的交互情况?Jamon主要是用来检jee的应用程序。它最新的版本?.1Q可以用?.4以上的jdk上?
二,jamon导入C的应用程序中?
首先下蝲jamon的开发包Q见我的附gQ同时你也可以去Sourceforge上自׃载。Sourceforge的下载地址为http://jamonapi.sourceforge.net。解压之后可以得C个jar包和一个war包。jar包是自己?x)用到的Q而war包是一个例子(不要看q个例子Q待?x)也要把它导入到目中?j)。把war包之间丢到服务器上,讉KQlocalhost:8080/jamon可以看到这个例子了(jin)Q这个例子是一个简单的性能监控pȝ?
接着把例子中的所有的包都导入到项目中Qƈ把war包中的jsp和imagesq有css都考到目中,比如新徏一个目录叫monitorQ它和W(xu)EB-INF是同U目录)(j)?
三,正确配置自己的应?
我们在性能监测的时候最监测的就是页面的讉K率和cMҎ(gu)的访问率。所以在q一部分主要讲解一下如何监自q面和类中方法的讉K?
1Q?(g)自q面讉K?
首先我们需要在web.xml中添加一个filterQ这个filter是用来判断哪些面需要被监视的,如下所C:(x)
q个cȝ上去很简单,其实也挺单的Q就是得到uriQ然后把它注册到MonitorFactorycM。这样只要我们去讉K刚才创徏的monitor目录下的jsp可以看到性能监测面?jin)?
2Q?Q接下来我们看看在用spring的情况下如何监测一个bean的方法调用。Spring也提供了(jin)对Jamon的支?spring支持的东西还真多?Q也是文章开头提出的那个拦截器,Z(jin)l我们的bean加上拦截器,我们在spring的applicationcontext配置文g中加入如下语句:(x)
上面q个是典型的spring的aop的配|,如果对spring的aop配置不了(jin)解的可以ȝ一下spring中文文档Q当然如果不想了(jin)解的话即使直接把q段配置拷到自己的项目中也是可以直接使用的?
q有一个步骤就是在你的log4j.properties中加入这句代码:(x)
如果没有q一行,那么q个拦截器是不会(x)把方法调用的信息向MonitorFactory注册的?
只需要这些步骤,userservice中的Ҏ(gu)在调用的时候就可以被拦截,然后其注册到MonitorFactory中去?jin)?
所有的配置完成之后我们来看一下效果吧:
http://www.javaeye.com/topics/download/b2bac96e-6c18-4340-b7e0-f84c7bb6adca从这个图上我们可以看刎ͼ所有页面被讉K的次敎ͼUserService中的getAllUsers被调用的ơ数Q最双的是讉K旉。这只是整个囄一部分Q当然这个页面中也包括每一个页面被讉K的次数和W一ơ访问的旉{等。下载附件运行,可以看到所有的面?jin)?
三,ȝ
Ҏ(gu)以上的步骤,我们可以监我们的E序?jin),应用E序中哪些页面被讉K的多Q哪些页面被讉K的少Q哪些方法被讉K的多Q哪些方法被讉K的少Q以?qing)访问高峰期集中在什么时间等{,有了(jin)q些参数Q我们更可以有针Ҏ(gu)的对应用程序进行优化了(jin)Q比如说某个面讉K比较频繁Q我可以用ehcache或oscachel这个页面做一个缓存。如果某个方法的讉K比较频繁那就看看q个Ҏ(gu)能否q一步优化,是需要异步,q是需要缓存,q是需要其他等{,M有了(jin)jamon可以l我们带来更多的便捷Q既可以让我们知道我们的客户的行为,也可以让我们知道我们开发的E序?#8220;能力”?
其实本文提供的只是对面和方法调用的监控Q但是jamon可以提供更多功能Q比如说sql语句的监控等{,q就需要我们共同去发掘?sh)(jin)?
附g中包括了(jin)一个easywebwork的例子,我把jamon导入到这个例子工E中去,大家可以直接下蝲q行观看效果。Easywebwork是一个旨在减webwork2.2.xpd的xml配置文g的项目,
如果对这个主题感兴趣请到
http://www.javaeye.com/topic/91614
http://www.javaeye.com/topic/93814
参加讨论?
之前有一文章讲到如何用jamon来监控请求以?qing)方法得调?原文地址见:(x)[url]http://www.javaeye.com/post/354575 [/url])Q本文属于其姊妹,使用jamon监控pȝ的sql调用?qing)其调用效率?
需求:(x)
1我们知道在用hibernate得时候,我们可以打开show sql选项Q可以直接查看sql语句调用的情况,那么当我们用其他持久技术的时候我们也需要这个功能怎么办呢Q没有关p,jamon能够帮我们做到?
2 很多时候,不同的程序员?sh)(x)写Z同的性能的sqlQ有时候可能会(x)不小?j)或者因Z知道而写出性能很差的sqlQ我自己曄发生过q种事情Q在500w条数据的表里使用?jin)一个limit来分,到后面,执行一条sql都需要几分钟Q诸如此cȝ时候可能大安有碰到过Q如果能有监控sql性能的工具嵌在应用里该多好,当然有jamon可以帮我们做到?
对于jamon来说Q每一个query的执行之后的l计l果都会(x)被保存(sh)来,q些概要l计都以MonProxy-SQL开头。这些统计中包括查询执行的时_(d)有比如^均时_(d)执行L_(d)最执行时_(d)最大执行时_(d)q些东西N不是我们正想要的吗?
那么让我们开始吧Q我们知道,q些query执行的统计应该是在connection中被l计的,也就是说我们要代理一般的connectionQ而connection又是由datasource产生的,所以我们可以代理datasourceQ说q就qӀ?
一个datasource接口中关于connection的方法只有两个:(x)
也就是说我们只要overrideq两个方法即可?
Ҏ(gu)q个思\我写?jin)以下代码?x)
昄q个一个代理模式。接下来是生成q个代理c?我是在spring中注册了(jin)q么一个类Q?
writeMonitorDataSource 所依赖的writeDataSource是我们真正配置的datasourceQ比如:(x)
好了(jin)Q那么在使用datasource的时候,我们应该用哪个呢Q当然是writeMonitorDataSourceq个里,我们可以把它注入ljdbcTemplateQ或者sessionfactoryQ或者其他需要用到datasource的地斏V?
到这里,׃切准备完毕了(jin)Q我们可以看看我们sql语句的执行效率了(jin)(q个面的地址为sql.jsp)Q?
见图1
当然要我们的应用能够昄q个面Q我们需要把jamon的一l页面拷到我们的应用中,q一l页面包含在我提供下载的包中Q最新的jamon版本?.7?
我们可以看到id?53的那条sql语句执行?8msQ我要去看看q条sql语句是不是有点什么问题或者是否有优化的可能性?
当然Q刚才说到每一条sql语句都是有统计^均时_(d)最大最执行时间等{,没错Q在另外一个页面jamonadmin.jsp上就包含q些内容
见图2
上面的图片代表hits表示执行ơ数Qavg表示sql执行的^均时_(d)后面的min和max表示sql执行的最耗时和最大耗时。从q里我们能够更直观的看到我们每条sql语句执行的情c(din)很有用的一个功能?
而且在上面那两个面上,我们q可以选择把sql执行的结果导出来Q可以导成xml或excel格式?
ȝQ用jamon来监控我们的sql语句我觉得很有用意义,而且使用jamonҎ(gu)们的应用来说完全是松耦合的,Ҏ(gu)不需要更Ҏ(gu)们的业务逻辑代码Q完全是可插拔的Q我们也可以开发时使用jamonQ部|时拔掉jamon。有?jin)它能够使一些程序员能够更多一点的x(chng)自己所写的sql的效率,当然如果之前开发的时候没有用jamon也没有关p,即上线后也可以查看一下sql语句是否有问题,比如哪些sql语句执行得比较频J,是否存在l其做缓存得可能性等{。M使用jamon在应用程序中来监控我们得sql语句h很强得实用意义,
再次ȝQjamonQ很好,很强大?
]]>
<default-config>
<!--当连接池中的q接耗尽的时?span class="hilite1">c3p0一ơ同时获取的q接数。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定义在从数据库获取新q接p|后重复尝试的ơ数。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--两次q接中间隔时_(d)单位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
<!--q接关闭旉认将所有未提交的操作回滚。Default: false -->
<property name="autoCommitOnClose">false</property>
<!--c3p0徏一张名为Test的空表,q用其自带的查询语句进行测试。如果定义了(jin)q个参数那么
属性preferredTestQuery被忽略。你不能在这张Test表上q行M操作Q它?yu)只?span class="hilite1">c3p0试
使用。Default: null-->
<property name="automaticTestTable">Test</property>
<!--获取q接p|会(x)引v所有等待连接池来获取连接的U程抛出异常。但是数据源仍有?
保留Qƈ在下ơ调用getConnection()的时候l尝试获取连接。如果设为trueQ那么在试
获取q接p|后该数据源将x(chng)已断开q永久关闭。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--当连接池用完时客L(fng)调用getConnection()后等待获取新q接的时_(d)时后将抛出
SQLException,如设?则无限期{待。单位毫U。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全\径?
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name="connectionTesterClassName"></property>
<!--指定c3p0 libraries的\径,如果Q通常都是q样Q在本地卛_获得那么无需讄Q默认null卛_
Default: null-->
<property name="factoryClassLocation">null</property>
<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.
Q文档原文)(j)作者强烈徏议不使用的一个属?->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--?0U检查所有连接池中的I闲q接。Default: 0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化时获取三个q接Q取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--最大空闲时?60U内未用则q接被丢弃。若?则永不丢弃。Default: 0 -->
<property name="maxIdleTime">60</property>
<!--q接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的标准参敎ͼ用以控制数据源内加蝲的PreparedStatements数量。但׃预缓存的statements
属于单个connection而不是整个连接池。所以设|这个参数需要考虑到多斚w的因素?
如果maxStatements与maxStatementsPerConnection均ؓ(f)0Q则~存被关闭。Default: 0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定义?jin)连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection"></property>
<!--c3p0是异步操作的Q缓慢的JDBC操作通过帮助q程完成。扩展这些操作可以有效的提升性能
通过多线E实现多个操作同时被执行。Default: 3-->
<property name="numHelperThreads">3</property>
<!--当用戯用getConnection()时root用户成ؓ(f)去获取连接的用户。主要用于连接池q接?span class="hilite1">c3p0
的数据源时。Default: null-->
<property name="overrideDefaultUser">root</property>
<!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->
<property name="overrideDefaultPassword">password</property>
<!--密码。Default: null-->
<property name="password"></property>
<!--定义所有连接测试都执行的测试语句。在使用q接试的情况下q个一显著提高?gu)试速度。注意:(x)
试的表必须在初始数据源的时候就存在。Default: null-->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--用户修改pȝ配置参数执行前最多等?00U。Default: 300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大请只在需要的时候用它。如果设为true那么在每个connection提交?
时候都校验其有效性。徏议用idleConnectionTestPeriod或automaticTestTable
{方法来提升q接试的性能。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--如果设ؓ(f)true那么在取得连接的同时校验连接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--用户名。Default: null-->
<property name="user">root</property>
<!--早期?span class="hilite1">c3p0版本对JDBC接口采用动态反代理。在早期版本用途广泛的情况下这个参?
允许用户恢复到动态反代理以解决不稳定的故障。最新的非反代理更快ƈ且已l开?
q泛的被使用Q所以这个参数未必有用。现在原先的动态反与新的非反代理同时受?
支持Q但今后可能的版本可能不支持动态反代理。Default: false-->
<property name="usesTraditionalReflectiveProxies">false</property>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">25</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">0</property>
<user-overrides user="swaldman">
</user-overrides>
</default-config>
<named-config name="dumbTestConfig">
<property name="maxStatements">200</property>
<user-overrides user="poop">
<property name="maxStatements">300</property>
</user-overrides>
</named-config>
</c3p0-config>
]]>
C3P0增加以下配置信息:
在配|文件中要写?nbsp; <property name="minPoolSize"><value>1</value></property> 格式
不能写成 q样<property name="properties">
<props>
<prop key="c3p0.initialPoolSize">1</prop>
</props>
</property>
c3p0不能完全识别!!