c3p0仅测试与master的连接,忽略slave

时间:2013-06-25 11:39:22

标签: mysql hibernate c3p0

我正在使用复制驱动程序com.mysql.jdbc.ReplicationDriver并使用jdbc配置我的连接

jdbc.de.url=jdbc:mysql:replication://master:3306,slave:3306/lieferando_de?zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8&tcpKeepAlive=true

c3p0配置为每30秒测试一次池连接

<bean id="basisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" abstract="true">
        <property name="driverClass" value="${jdbc.driverClassName}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="minPoolSize" value="5" />
        <property name="maxPoolSize" value="30" />
        <property name="maxIdleTime" value="14400" />
        <property name="maxConnectionAge" value="14400" />
        <property name="testConnectionOnCheckout" value="false" />
        <property name="idleConnectionTestPeriod" value="30" />
        <property name="preferredTestQuery" value="SELECT 1" />
    </bean>

但我看到只有主人正在接受测试

[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0 Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@6b6a16ae] on IDLE CHECK.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1 Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@5c219c51] on IDLE CHECK.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@7e350225] on IDLE CHECK.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1 Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@5c219c51] on IDLE CHECK has SUCCEEDED.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1 Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@602f892f] on IDLE CHECK.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0 Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@6b6a16ae] on IDLE CHECK has SUCCEEDED.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0 Testing PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@7deb41d6] on IDLE CHECK.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@7e350225] on IDLE CHECK has SUCCEEDED.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1 Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@602f892f] on IDLE CHECK has SUCCEEDED.
[DEBUG] 25.06.2013 13:29:30 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0 Test of PooledConnection [com.mchange.v2.c3p0.impl.NewPooledConnection@7deb41d6] on IDLE CHECK has SUCCEEDED.

最初与主设备和从设备的连接是打开的,计数为5

macbookpro-533f:~ mlaug$ netstat -nat | grep 3306
tcp4       0      0  10.10.14.181.57215     slave.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57214     slave.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57213     master.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57212     master.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57211     slave.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57209     slave.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57210     slave.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57208     master.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57207     master.3306     ESTABLISHED
tcp4       0      0  10.10.14.181.57206     master.3306     ESTABLISHED

但是从属连接在5分钟后消失,导致应用程序抛出Broken Pipe Exception

如何配置c3p0以测试从属连接?

1 个答案:

答案 0 :(得分:0)

为我解决问题的是c3p0的DefaultConnectionTester的自己实现并配置它

<property name="connectionTesterClassName" value="x.y.z.QueryReplicationConnectionTester" />

并使用以下实现

public class QueryReplicationConnectionTester extends DefaultConnectionTester{

    private static final long serialVersionUID = -3450145378350470297L;

    /**
     * during testing we need to make sure, that not only master
     * but also the slave connection is used. Therefore we need to set
     * the connection to "readonly" to make sure, that the slave 
     * connection is used.
     * 
     * CAUTION: this will only work for ONE SLAVE ENVIRONMENT, since
     * this does not make sure all slaves are checked.
     */
    @Override
    public int activeCheckConnection(Connection connection, String arg1, Throwable[] arg2) {

        // Initially set to ok
        int status = CONNECTION_IS_OKAY;

        try {

                    // remember state and 
            boolean autoCommit = connection.getAutoCommit();
                    boolean readOnly = connection.isReadOnly();

            // switch to slave and check slave
            connection.setReadOnly(true);
            connection.setAutoCommit(false);
            status = super.activeCheckConnection(connection, arg1, arg2);

            // if slave is fine, lets check the master
            if ( status == CONNECTION_IS_OKAY ){
                connection.setReadOnly(false);
                connection.setAutoCommit(autoCommit);
                status = super.activeCheckConnection(connection, arg1, arg2);
            }

            connection.setAutoCommit(autoCommit);
            connection.setReadOnly(readOnly);

        } catch (SQLException e) {
            status = CONNECTION_IS_INVALID;
        }

        // return final state
        return status;
    }

}