resin不断重启分析 博客分类: java Pool closed dbcpunable to create new native threadoutOfMemoryError
线上resin服务跑一段时间就会抛出以下这个异常,导致服务不断重启,用的是spring+ibatis+mysql
这个问题如何解决?
数据库连接池配置:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${env.mysql.jdbc.url}" />
<property name="username" value="${env.mysql.username}" />
<property name="password" value="${env.mysql.password}" />
<property name="defaultAutoCommit" value="true"></property>
</bean>
Caused by: java.lang.IllegalStateException: Pool closed
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1132)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:115)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:430)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:202)
... 50 more
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.lang.IllegalStateException: Pool closed
异常追加:java.lang.outOfMemoryError:unable to create new native thread
导致resin不断的重启
问题分析:
线上服务resin不断自动重启,出现了2次,异常如上,
第一次出现后分析可能有两种原因:
1.可能是程序里面线程池的数目设置过大
2.数据库最大链接数目设置不合理
所以根据以上2点做了相关优化,调小程序里面连接池的数目,将数据库最大链接数调大
优化完毕后,貌似起到了一定的效果。可是一个多月后这个问题再次重现,并且这次持续时间相当长,大约有半个小时。
痛定思痛,又根据异常分析,表面上看是线程数创建过多,导致内存溢出,没有足够的内存创建新的线程,网站上的表象就是访问超慢或者压根访问不了。
由于程序已经正常运行了半个月,先排除代码的问题。猜测是不是数据库方面的原因,随即联系dba找出当时异常时间点数据库方面的相关日志,发现在resin不断重启前,有几个sql执行的效率相当低下,达到了好几百秒,这完全已经不正常。由于执行相当慢,表被锁了,但大量的查询还在不断的涌入,大量sql直接被阻塞,数据库链接耗尽,无法创建新的链接。线程数目不断的增加,旧有线程占用内存又没释放,直到web容器的承受不了后,就开启了自动重启的保护机制。
解决方案:找出了那几个查询相当慢的sql。逐个进行分析,对sql进行优化,对于优化效果不大的,从业务层上进行解决(多次查询,降低占用数据库连接的时间)。
优化完毕后,重新部署运行,持续观察中。。。。。