8時間のアイドル時間後のMysql接続無効化の問題を解決します

ブロガーは、前回のブログ投稿で、mysqlまたはOracleへの高速書き込みの問題についてブログを投稿しました。書き込みパフォーマンスは向上しましたが、他のプロジェクトの開発プロセスで、接続接続の失敗の問題が発生しました。

ブロガーの使用シナリオは次のとおりです。

ブロガーのプロジェクトはリアルタイムのプッシュプロジェクトです。プッシュが成功するたびに、mysqlデータの一部が挿入されます。夜間のユーザーへのプッシュはユーザーの邪魔になる可能性があるため、ユーザーは22から07にプッシュされません。そのため、ギャップ期間中はmysql接続が使用されないため、接続接続の失敗が報告されます。この時点では、ブロガーが言及した高性能のwrite mysqlソリューションは機能しません。これは、その方法では接続を設定できないためです。障害時間と検出済み、c3p0の場合は理想的ではありませんが、今回はブロガーがDBCP接続プールを使用しました。
Mavenを使用

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.5.0</version>
        </dependency>

私が使用するツールは次のとおりです

package com.chinaTelecom.mySqlUtiles;

import org.apache.commons.dbcp2.BasicDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBCPUtils {
    //建立连接的驱动驱动名称
    public static final String DRIVER_CLASS_NAME = "***";
    //数据库链接数据哭的url
    public static final String URL = "***";
    //链接的数据库账号
    public static final String USERNAME = "***";
    //链接的数据库密码
    public static final String PASSWORD = "***";
    //初始化时链接池的数量
    private static final int INITIAL_SIZE = 10;
    //的到链接实例
    private static BasicDataSource dataSource = new BasicDataSource();
    //初始化链接参数
    static{
        dataSource.setDriverClassName(DRIVER_CLASS_NAME);
        dataSource.setUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);

        dataSource.setInitialSize(INITIAL_SIZE);   //初始化连接:连接池启动时创建的初始化连接数量
        dataSource.setMaxTotal(10);
        dataSource.setMaxIdle(6);   //最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制
        dataSource.setMinIdle(4);   //最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建
        dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 60 * 10);  //连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒
        dataSource.setTestOnBorrow(true);  //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.
        dataSource.setTestOnCreate(true);  //指明对象在创建后是否需要验证是否有效,如果对象验证失败,则触发对象创建的租借尝试将失败。
        dataSource.setTestWhileIdle(true);  //指明对象是否需要通过对象驱逐者进行校验(如果有的话),假如一个对象验证失败,则对象将被从池中释放。和timeBetweenEvictionRunsMillis配合使用。
        dataSource.setTimeBetweenEvictionRunsMillis(100000); //在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位,即每100秒做一次idle连接的检测,检测语句为validationQuery。
        dataSource.setValidationQuery("select 1"); //SQL查询,用来验证从连接池取出的连接,验证连接是否有效,查询必须是一个SQL SELECT并且必须返回至少一行记录。
        dataSource.setNumTestsPerEvictionRun(10);  //每次空闲连接回收器线程运行时检查的连接数量
    }
    //提供获得数据源
    public static DataSource getDateSource(){
        return dataSource;
    }
    //提供获得链接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

	//测试connection是否正常
    public static void main(String[] args) throws SQLException {
        Connection connection = DBCPUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("select * from phoneNum");
        ResultSet rs = ps.executeQuery();
        while (rs.next()){
            String string = rs.getString(2);
            System.out.println(string);
        }
    }
}

パラメータの解釈
testOnBorrow = falseは、接続プールで接続を使用するときに検出が実行されないことを意味します。これも推奨される構成です。trueに設定すると、データベースのパフォーマンスに影響します。

testWhileIdle = trueは、接続がアイドル状態の接続コレクターによってテストされるかどうかを示します。テストが失敗した場合、接続はプールから削除され、timeBetweenEvictionRunsMillisと組み合わせて使用​​されます。

validateQuery = select 1 SQLクエリ。接続プールから取得された接続を検証し、接続が有効かどうかを検証するために使用されます。クエリはSQL SELECTであり、少なくとも1行のレコードを返す必要があります。

timeBetweenEvictionRunsMillis = 100000アイドル接続コレクタースレッドの実行中のスリープ時間の値(ミリ秒単位)。つまり、アイドル接続チェックは100秒ごとに実行され、チェックステートメントはvalidationQueryです。

minEvictableIdleTimeMillis = 600000接続は、アイドル接続コレクタスレッドでなくてもプール内でアイドル状態に保たれます。つまり、アイドル接続の保存時間は600秒(10分)です。

問題ありません。アイドルスレッドの検出は100秒ごとに実行されます。アプリケーションの検出時間は600秒で、データベースで設定されている1800秒よりも短いです。異常な接続障害が発生するのはなぜですか。そして、報告された接続障害時間はますます長くなっています。

分析
dbcpソースコードを見て、アイドル接続コレクタースレッドが実行されるたびにチェックされる接続数であるパラメーターnumTestsPerEvictionRunもあることを確認します。このパラメーターは、100秒ごとに検出されるアイドルスレッドの数を構成します。このパラメーターは構成しませんでしたが、デフォルト値です。

protected int numTestsPerEvictionRun = 3;

ソースコードの構成は3です。これは、デフォルトで毎回3つのアイドルスレッドのみが検出されることを意味します。

最悪の場合、最大のアイドルスレッドは800であり、3つのアイドルスレッドの判定は100秒ごとに実行されます。すべてのアイドルスレッドのステータスを判断するには、(800/3)* 100秒= 26666秒かかります。データベースのタイムアウトは1800秒です。つまり、プールがいっぱいの場合(またはプール内に多数の接続がある場合)、すべてのアイドルスレッドがテストされるまで、アプリケーションは失敗した接続をフェッチする可能性が高くなります。最も早いタイムアウト接続は30分後である必要があります。これは、データベース構成では1800秒です。

解決策
インターネット上のすべてのユーザーに推奨される構成は、numTestsPerEvictionRun = maxIdleを設定することです。これにより、1回のテスト後にすべての無効なアイドルをスレッドプールから削除して、ピーク後に接続プール接続が失敗する問題を回避できます。

無効な接続はゆっくりと削除されるため、その時点では構成変更操作は行われていません。その後、numTestsPerEvictionRunパラメーターがmaxIdleと同じ値に構成され、この問題を回避できます。

おすすめ

転載: blog.csdn.net/qq_44962429/article/details/106320820