【问题标题】:Resuming an application from sleep causes 'Communications link failure'从睡眠状态恢复应用程序会导致“通信链路故障”
【发布时间】:2012-09-11 12:56:22
【问题描述】:

我配置了一个运行良好的 CloudBees Run@cloud 实例,但在一段时间不活动后它被停用,然后似乎连接池未正确刷新。

当我返回网站时,前几个请求超时:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 4,746,680 milliseconds ago.  The last packet sent successfully to the server was 0 milliseconds ago.
    sun.reflect.GeneratedConstructorAccessor86.newInstance(Unknown Source)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
    com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
    com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3092)
    com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2978)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3526)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1989)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2150)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2620)
    com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5022)
    org.apache.tomcat.dbcp.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:371)
    org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.java:328)
    org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:87)
    org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)

我正在使用 cloudbees-web.xml 文件中配置的数据源通过 JNDI 进行连接:

    <resource name="jdbc/myapp" auth="Container" type="javax.sql.DataSource">
        <param name="username" value="myuser" />
        <param name="password" value="mypass" />
        <param name="url" value="jdbc:cloudbees://myurl />
    </resource>

我是否缺少某些配置,或者这是服务器中连接池配置的错误?

【问题讨论】:

    标签: mysql timeout connection-pooling cloudbees


    【解决方案1】:

    [来自 CloudBees Wiki 上的 Database Guide]

    MySQL 包含一个超时功能,它将关闭长时间空闲的连接。为了提高数据库性能,CloudBees 数据源使用 Apache DBCP 连接池在应用程序关闭 JDBC 连接后重用它们。

    如果您使用的连接在池中空闲时间过长,您的应用程序可能会遇到以下错误:“从服务器成功接收的最后一个数据包是 XXX 秒前”。

    连接池包含一个设置,当调用 javax.sql.DataSource.getConnection() 时将验证并丢弃死连接。要使用此设置,请将以下 XML 参数添加到 cloudbees-web.xml 中的 DataSource 定义中。

    <param name="validationQuery" value="SELECT 1" />
    <param name="testOnBorrow" value="true" />
    

    因此,对于您的资源,您应该能够执行以下操作:

    <resource name="jdbc/myapp" auth="Container" type="javax.sql.DataSource">
        <param name="username" value="myuser" />
        <param name="password" value="mypass" />
        <param name="url" value="jdbc:cloudbees://myurl />
        <param name="validationQuery" value="SELECT 1" />
        <param name="testOnBorrow" value="true" />
    </resource>
    

    如果您使用 bees app:bind 命令而不是 cloudbees-web.xml 来注入数据源,则可以使用这些参数作为命令的参数

    bees app:bind -a APP_ID -db DB_NAME -as JNDI_ALIAS validationQuery="SELECT 1" testOnBorrow=true
    

    【讨论】:

    • 请注意 testOnBorrow 将导致每次从池中获取连接时都执行 SELECT 1,例如实际上对于每个执行的查询。使用 minEvictableIdleTimeMillis、timeBetweenEvictionRunsMillis 和 numTestsPerEviction 在特定超时后逐出连接,如此处所述juststuffreally.blogspot.de/2007/10/… 对于 DBCP 池可能是一个更好的主意。或者,您可以尝试 testWhileIdle 而不是 testOnBorrow。
    猜你喜欢
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2012-05-27
    • 1970-01-01
    • 2018-02-17
    • 2012-10-14
    • 2011-08-12
    相关资源
    最近更新 更多