Подтвердить что ты не робот

Ошибка таймаута подключения к MySQL - приложение Grails для Tomcat с использованием Hibernate и ORM

У меня есть небольшое приложение grails, работающее на Tomcat в Ubuntu на VPS. Я использую MySql в качестве своего хранилища данных, и все работает нормально, если я не выхожу из приложения более полудня (8 часов?). Я сделал несколько поисков и, по-видимому, это по умолчанию wait_timeout в mysql.cnf, поэтому через 8 часов соединение будет умирать, но Tomcat не будет знать этого, когда следующий пользователь попытается просмотреть сайт, он увидит ошибку сбоя подключения. Обновление страницы исправит это, но я хочу полностью избавиться от ошибки. Для моей версии MySql (5.0.75) у меня есть только my.cnf, и он не содержит такого параметра. В любом случае изменение этого параметра не решит проблему.

Этот Сообщение в блоге, похоже, сообщает об аналогичной ошибке, но я до сих пор не совсем понимаю, что мне нужно настроить, чтобы получить это исправленное и также я надеюсь, что есть более простое решение, чем другая сторонняя библиотека. У машины, на которой я запущен, есть RAM 256 МБ, и я пытаюсь свести к минимуму количество программ/служб.

Есть ли что-то, что я могу настроить в Grails/Tomcat/MySql, чтобы уйти?

Спасибо заранее,

Гав

От моего 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
4b9b3361

Ответ 1

Ссылаясь на статью у вас есть устаревшие подключения в пуле соединений DBCP, которые молча удаляются операционной системой или брандмауэром.

Решение состоит в том, чтобы определить запрос проверки и выполнить проверку работоспособности соединения до его фактического использования в приложении. В grails это делается, изменяя файл grails-app/conf/ spring/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"
  }
} 

Ответ 2

В grails 1.3.X вы можете изменить значения evictor в файле 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 с низким значением.

Ответ 3

Попробуйте увеличить количество открытых подключений MySQL, поместив в DataSources.groovy следующее:

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

Если вы хотите пройти весь свиньи, попробуйте реализовать пул соединений; здесь полезная ссылка.

Ответ 4

Для 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

Ответ 5

Добавьте эти параметры в dataSource

        testOnBorrow = true
        testWhileIdle = true
        testOnReturn = true

См. эту статью для получения дополнительной информации http://sacharya.com/grails-dbcp-stale-connections/

Ответ 6

Начиная с 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
    }

Ответ 7

Как выглядит ваша строка соединения JDBC? Вы можете установить параметр autoReconneect в конфигурацию источника данных, например.

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