MySQL连接超时问题 - 在Tomcat上使用休眠和ORM的Grails应用程序

问题描述:

我在VPS上的Ubuntu上的Tomcat上运行了一个小型的grails应用程序。我使用MySql作为我的数据存储,一切工作正常,除非我离开应用半天以上(8小时?)。我做了一些搜索,显然这是mysql.cnf中的默认wait_timeout,所以在8小时后,连接将会终止,但当下一个用户尝试查看站点时,Tomcat不会知道,他们将看到连接失败错误。刷新页面将解决这个问题,但我想完全摆脱错误。对于我的MySql版本(5.0.75),我只有my.cnf,并且它不包含这样的参数,在任何情况下,更改此参数都不能解决问题。MySQL连接超时问题 - 在Tomcat上使用休眠和ORM的Grails应用程序

这个Blog Post似乎报告了一个类似的错误,但我仍然不完全理解我需要配置得到这个固定的,我希望有一个比另一个第三方库更简单的解决方案。我正在运行的机器有256MB内存,我正在努力将运行的程序/服务数量降到最低。

有没有什么我可以在Grails/Tomcat/MySql中配置让它消失?

由于提前,

GAV株系

从我的catalina.out的;

2010-04-29 21:26:25,946 [http-8080-2] ERROR util.JDBCExceptionReporter - The last packet successfully received from the server was 102,906,722 milliseconds$ 
2010-04-29 21:26:25,994 [http-8080-2] ERROR errors.GrailsExceptionResolver - Broken pipe 
java.net.SocketException: Broken pipe 
     at java.net.SocketOutputStream.socketWrite0(Native Method) 
     ... 
2010-04-29 21:26:26,016 [http-8080-2] ERROR util.JDBCExceptionReporter - Already closed. 
2010-04-29 21:26:26,016 [http-8080-2] ERROR util.JDBCExceptionReporter - Already closed. 
2010-04-29 21:26:26,017 [http-8080-2] ERROR servlet.GrailsDispatcherServlet - HandlerInterceptor.afterCompletion threw exception 
org.hibernate.exception.GenericJDBCException: Cannot release connection 
     at java.lang.Thread.run(Thread.java:619) 
Caused by: java.sql.SQLException: Already closed. 
     at org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:84) 
     at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.close(PoolingDataSource.java:181) 
     ... 1 more 

参考此article,您的DBCP连接池中已陈旧的连接被操作系统或防火墙无提丢弃。

解决方案是定义一个验证查询,并在实际在应用程序中使用它之前对连接进行完整性检查。 Grails中这实际上是通过修改的grails-app/conf目录/春/ Resource.groovy文件,并添加做了以下:

beans = { 
    dataSource(BasicDataSource) { 
    //run the evictor every 30 minutes and evict any connections older than 30 minutes. 
    minEvictableIdleTimeMillis=1800000 
    timeBetweenEvictionRunsMillis=1800000 
    numTestsPerEvictionRun=3 
    //test the connection while its idle, before borrow and return it 
    testOnBorrow=true 
    testWhileIdle=true 
    testOnReturn=true 
    validationQuery="SELECT 1" 
    } 
} 
+0

是否与grails-app/conf/spring/resources.groovy一样是grails-app/conf/spring/Resource.grooy?我使用grails 1.2.1,当我添加它时,我遇到了这个错误: === 无法为连接URL创建类''的JDBC驱动程序'null' java.sql.SQLException:没有合适的驱动程序 = == – firnnauriel 2010-07-22 09:03:58

+0

的确,它正在工作,如果我创建了一个新的Resource.groovy。这很好,现在我猜。 – firnnauriel 2010-07-22 09:12:53

+0

@firnnauriel当你创建Resource.groovy文件时,这实际上做了你想要的吗? – skaz 2011-08-31 19:46:17

尝试通过把你的DataSources.groovy以下提高开放的MySQL连接数:

dataSource { 
    driverClassName = "com.mysql.jdbc.Driver" 
    pooled=true 
    maxActive=10 
    initialSize=5 
    // Remaining connection params 
} 

如果要干到底,尽量实现一个连接池;这里是一个useful link

你的JDBC连接字符串是什么样的?您可以在数据源配置中设置一个autoReconneect参数,例如

jdbc:mysql://hostname/mydb?autoReconnect=true 
+0

不为我工作。据我所知,这只会在尝试失败后重新建立连接,并且它仍会返回一个异常。 – mcv 2011-01-18 09:47:19

Grails的1.3.X,我不得不将以下代码添加到BootStrap.groovy中:

def init = {servletContext -> 
    def ctx=servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT) 

    //implement test on borrow 
    def dataSource = ctx.dataSource 
    dataSource.targetDataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 30) 
    dataSource.targetDataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30) 
    dataSource.targetDataSource.setNumTestsPerEvictionRun(3) 
    dataSource.targetDataSource.setTestOnBorrow(true) 
    dataSource.targetDataSource.setTestWhileIdle(true) 
    dataSource.targetDataSource.setTestOnReturn(false) 
    dataSource.targetDataSource.setValidationQuery("SELECT 1") 

    } 

我也不得不进口org.codehaus.groovy.grails.commons.ApplicationAttributes

Grails中1.3.X,你可以修改DataSource.groovy文件中逐出值让苏在空闲期间使用重新连接的连接。这将确保mysql服务器不会超时连接。

production { 
    dataSource { 
    pooled = true 
    // Other database parameters.. 
    properties { 
     maxActive = 50 
     maxIdle = 25 
     minIdle = 5 
     initialSize = 5 
     minEvictableIdleTimeMillis = 1800000 
     timeBetweenEvictionRunsMillis = 1800000 
     maxWait = 10000 
    } 
} 

一个快速的方法来验证这个作品是修改的MySQL my.cnf配置文件[MySQL的]元素和具有低值添加WAIT_TIME参数。

grails 2.3.6默认配置开始已经为防止因超时而

关闭连接这些都是新的默认选项。

properties { 
     // See http://grails.org/doc/latest/guide/conf.html#dataSource for documentation 
     .... 
     minIdle = 5 
     maxIdle = 25 
     maxWait = 10000 
     maxAge = 10 * 60000 
     timeBetweenEvictionRunsMillis = 5000 
     minEvictableIdleTimeMillis = 60000 
     validationQuery = "SELECT 1" 
     validationQueryTimeout = 3 
     validationInterval = 15000 
     testOnBorrow = true 
     testWhileIdle = true 
     testOnReturn = false 
     jdbcInterceptors = "ConnectionState;StatementCache(max=200)" 
     defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED 
    } 

这些参数添加到数据源

 testOnBorrow = true 
     testWhileIdle = true 
     testOnReturn = true 

请参阅本文的详细信息 http://sacharya.com/grails-dbcp-stale-connections/