【问题标题】:Grails 2.3.4 Pool empty. Unable to fetch a connection in 30 secondsGrails 2.3.4 池为空。无法在 30 秒内获取连接
【发布时间】:2014-02-19 10:59:50
【问题描述】:

我们在 tomcat 7.0.30 中损坏了 grails 应用程序。 Grails 版本是 2.2.4,去年运行非常稳定。 我尝试将 grails 版本切换到 2.3.4,在测试环境中它运行正常(没有任何问题)。 但是当我在 20 分钟后将其投入生产时,我开始出现以下异常

[ajp-bio-9009-exec-430] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000].. Stacktrace follows:
org.apache.tomcat.jdbc.pool.PoolExhaustedException: [ajp-bio-9009-exec-430] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000].
        at grails.gorm.DetachedCriteria$_count_closure4.doCall(DetachedCriteria.groovy:686)
        at grails.gorm.DetachedCriteria$_withPopulatedQuery_closure10.doCall(DetachedCriteria.groovy:931)
        at org.grails.datastore.gorm.GormStaticApi$_withDatastoreSession_closure20.doCall(GormStaticApi.groovy:680)
        at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
        at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
        at org.grails.datastore.gorm.GormStaticApi.withDatastoreSession(GormStaticApi.groovy:679)
        at grails.gorm.DetachedCriteria.withPopulatedQuery(DetachedCriteria.groovy:913)
        at grails.gorm.DetachedCriteria.count(DetachedCriteria.groovy:684)
        at grails.gorm.DetachedCriteria.count(DetachedCriteria.groovy:683)
        at com.webbfontaine.wftaglib.BeanDataLoadController.doLoadData(BeanDataLoadController.groovy:30)
        at com.webbfontaine.wftaglib.BeanDataLoadController$_closure1.doCall(BeanDataLoadController.groovy:14)
        at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
        at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
        at org.josso.tc70.agent.SSOAgentValve.invoke(SSOAgentValve.java:684)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

在我们的应用程序中,所有对 DB 的查询都是通过 Grails GORM 完成的,我们不使用任何 SQL 或 HQL 查询。

我的猜测是 grails 2.3.4 本身有问题(某些连接未正确关闭/返回到池中)。

我错过了什么或它的 grails 问题吗? 有什么想法吗?

【问题讨论】:

    标签: tomcat grails grails-orm


    【解决方案1】:

    Grails 2.3.x replaced Commons DBCP with Tomcat JDBC,这可能是您的应用程序不同的原因。您可以检查池配置中的差异。

    【讨论】:

    • 感谢塞尔吉奥的回答。我想用 grails 2.3.x 和“Commons DBCP”来检查它。你知道如何强制 grails 使用“Commons DBCP”吗?
    • 我认为你需要做这样的事情doWithSpring,改变dataSource bean的类名。
    【解决方案2】:

    a few bugs in Grails in dataSource default settings。这些问题将在 Grails 2.3.6 中修复。

    以下是 MySQL 优化数据源设置的示例

    dataSource {
        pooled = true
        dbCreate = "update"
        url = "jdbc:mysql://localhost:3306/my_database"
        driverClassName = "com.mysql.jdbc.Driver"
        dialect = org.hibernate.dialect.MySQL5InnoDBDialect
        username = "username"
        password = "password"
        properties {
           // Documentation for Tomcat JDBC Pool
           // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes
           // https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html
           jmxEnabled = true
           initialSize = 5
           maxActive = 50
           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
           ignoreExceptionOnPreLoad = true
           // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#JDBC_interceptors
           jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
           defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED // safe default
           // controls for leaked connections 
           abandonWhenPercentageFull = 100 // settings are active only when pool is full
           removeAbandonedTimeout = 120
           removeAbandoned = true
           // use JMX console to change this setting at runtime
           logAbandoned = false // causes stacktrace recording overhead, use only for debugging
           // JDBC driver properties
           // Mysql as example
           dbProperties {
               // Mysql specific driver properties
               // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
               // let Tomcat JDBC Pool handle reconnecting
               autoReconnect=false
               // truncation behaviour 
               jdbcCompliantTruncation=false
               // mysql 0-date conversion
               zeroDateTimeBehavior='convertToNull'
               // Tomcat JDBC Pool's StatementCache is used instead, so disable mysql driver's cache
               cachePrepStmts=false
               cacheCallableStmts=false
               // Tomcat JDBC Pool's StatementFinalizer keeps track
               dontTrackOpenResources=true
               // performance optimization: reduce number of SQLExceptions thrown in mysql driver code
               holdResultsOpenOverStatementClose=true
               // enable MySQL query cache - using server prep stmts will disable query caching
               useServerPrepStmts=false
               // metadata caching
               cacheServerConfiguration=true
               cacheResultSetMetadata=true
               metadataCacheSize=100
               // timeouts for TCP/IP
               connectTimeout=15000
               socketTimeout=120000
               // timer tuning (disable)
               maintainTimeStats=false
               enableQueryTimeouts=false
               // misc tuning
               noDatetimeStringSync=true
           }
        }
    }
    

    【讨论】:

    【解决方案3】:

    我会首先检查是否有线程“卡住”并保持数据库连接。您可以从 JVM 线程转储中看到这一点。

    您可以在 unix 中通过向 Java 进程 PID 发送 SIGQUIT (3) 信号来执行线程转储。 您可以使用“kill -3 PID”命令来执行此操作。 threaddump 进入标准输出(默认情况下进入 tomcat 上的 catalina.out)。它不会终止 Java 进程,因此您可以在生产环境中正常使用此方法。

    获取线程转储的另一种方法是使用“jstack PID”命令。

    通常每隔几秒钟进行几次后续转储是值得的。通过这种方式,您可以区分转储以查看哪些变化以及哪些保持不变。您通常必须手动进行差异化。

    【讨论】:

      猜你喜欢
      • 2017-03-31
      • 2012-12-08
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2017-01-11
      • 2018-03-18
      相关资源
      最近更新 更多