ご利用の Java アプリケーションが ApsaraDB RDS for MySQL に頻繁に短時間接続を開いたり、インスタンスの最大接続数制限に達したりする場合、Druid は再利用可能な接続のプールを保持するため、アプリケーションはリクエストごとに完全な TCP ハンドシェイクのコストを支払う必要がありません。
前提条件
開始する前に、以下を確保してください。
アプリケーションサーバに Java 開発キット (JDK) 1.8 以降がインストールされていること
サーバの IP アドレスが RDS インスタンスの IP アドレスホワイトリストに追加されていること。「IP アドレスホワイトリストを構成する」をご参照ください。
ご利用のアプリケーションが RDS インスタンスと同じリージョンと仮想プライベートクラウド (VPC) 内の Elastic Compute Service (ECS) インスタンスで実行されている場合、ホワイトリストの構成は不要です。
プロジェクトのセットアップ
以下の手順では、Apache Maven プロジェクトを例として使用します。Maven プロジェクトは、Java ソースファイルを src/main/java に、リソースファイルを src/main/resources に格納します。pom.xml ファイルはプロジェクトの依存関係を管理します。
Druid を依存関係として追加する
pom.xml の dependencies セクションに以下を追加します。Druid 1.2.13 以降を使用してください。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.19</version>
</dependency>druid-spring-boot-starter を使用する場合、それがもたらす推移的な Druid 依存関係を除外し、バージョンが制御されるように Druid を明示的に再追加します。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.19</version>
</dependency>RDS インスタンスへの接続
ステップ 1: 接続プール構成ファイルを作成する
src/main/resources に druid.properties を以下の内容で作成します。
ご利用の RDS インスタンスのエンドポイントとポートを見つけるには、「インスタンスのエンドポイントとポートの表示と管理」をご参照ください。
# Driver class — do not modify
driverClassName=com.mysql.jdbc.Driver
# Replace with your RDS endpoint, database name, username, and password
url=jdbc:mysql://rm-bp**************.mysql.rds.aliyuncs.com:3306/database
username=****
password=****
# Connection pool sizing
initialSize=20
minIdle=20
maxActive=100
# Connection lifecycle
phyTimeoutMillis=3600000
# Wait and timeout settings
maxWait=5000
connectTimeout=20000
socketTimeout=60000
# Idle connection validation
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
# PreparedStatement cache
poolPreparedStatements=true
maxPoolPreparedStatementPerConnectionSize=100ステップ 2: 接続プールを初期化し、データベースにアクセスする
src/main/java に DruidPoolDemo クラスを作成します。これはクラスパスから druid.properties をロードし、DruidDataSourceFactory でプールを初期化し、その後のデータベース操作のために DataSource を公開します。
package com.aliyun.rdsfinops.collector.impl;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DruidPoolDemo {
private static DataSource dataSource = null;
String tableName = "sql_table_test";
// Load druid.properties and initialize the connection pool at class load time
static {
Properties properties = new Properties();
InputStream inputStream = DruidPoolDemo.class.getClassLoader()
.getResourceAsStream("druid.properties");
try {
properties.load(inputStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
Database operations are defined in the following methods:
Create a table: public void createTable()
Insert data: public void insertData()
Query data: public void selectData()
Delete data: public void deleteData()
*/
}接続プールパラメーター
稼働中のシステムでパラメーター値を変更する前に、本番ワークロードに対して完全な性能テストを実行してください。
推奨パラメーター
これらのパラメーターには、自明でないデフォルト値または安定性を静かに低下させる可能性のある不正確なデフォルト値があります。それらを確認し、明示的に設定してください。
| パラメーター | デフォルト | 推奨 | 説明 |
|---|---|---|---|
initialSize | 0 | 20–80 | 起動時に確立される接続数。アプリケーション起動直後に負荷を処理できるよう、平均同時接続数の 60~80% に設定します。 |
minIdle | 0 | 20–80 | バーストトラフィックのために予備として保持される最小アイドル接続数。initialSize または低負荷期間中に Java 仮想マシン (JVM) が保持する接続数と一致させます。 |
maxActive | 8 | 100 | 最大アクティブ接続数。データベースが処理できるピーク時の同時接続数に、トラフィックスパイクのための余裕を持たせて設定します。 |
phyTimeoutMillis | -1 (制限なし) | 3,600,000–28,800,000 | 物理接続が Druid によって強制的に閉じられ、再作成されるまでの最大時間 (ミリ秒)。デフォルト値の -1 は、接続が常に再利用可能であることを指定します。このパラメーターは、ビジネス要件に基づいて構成してください。このパラメーターは、長時間アイドル状態の接続を防ぎ、リソースを節約するために使用されます。 |
maxWait | -1 (無期限に待機) | 5,000 | プールが枯渇しているときに接続を待機する最大時間 (ミリ秒)。これを -1 (スレッドが無期限にブロックされる) または 0 (リクエストがすぐに失敗する) に設定しないでください。通常の条件下では、接続の取得には 10~30 ミリ秒かかります。5,000 ミリ秒は十分なバッファーを提供します。 |
connectTimeout | 10,000 | 3,000 | RDS サーバーへの新しい接続を確立する際の TCP 接続タイムアウト (ミリ秒)。アプリケーションとインスタンス間のネットワーク遅延に基づいて調整します。 |
socketTimeout | 10,000 | 10,000–60,000 | SQL ステートメントを送信した後、データベースが応答するまでの待機時間 (ミリ秒)。これを低く設定しすぎないでください。クエリが正当に長時間実行される場合、接続は破棄されます。この値を減らす前に、遅いクエリを調査してください。 |
testWhileIdle | false | true | このパラメーターを true に設定することを推奨します。接続プールはアイドル接続の状態を定期的にチェックします。 |
オプションパラメーター
| パラメーター | デフォルト | 推奨 | 説明 |
|---|---|---|---|
poolPreparedStatements | true | true | 接続ごとに PreparedStatement オブジェクトをキャッシュします。同じステートメントが繰り返し実行される場合の SQL コンパイルオーバーヘッドを削減し、SQL インジェクションの防止に役立ちます。クエリが大幅に異なる場合や、過剰な JVM メモリを消費する大規模な結果セットを伴う場合は、無効にしてください。 |
maxPoolPreparedStatementPerConnectionSize | 10 | 100 | 接続ごとにキャッシュされる PreparedStatement オブジェクトの最大数。アプリケーションが多くの個別のパラメーター化されたクエリを実行する場合は、増やしてください。メモリ負荷を防ぐため、非常に大きな値は避けてください。 |
デフォルトパラメーター
これらのパラメーターは、ほとんどのユースケースでデフォルト値のままでうまく機能します。特定の要件がある場合にのみ変更してください。
| パラメーター | デフォルト | 説明 |
|---|---|---|
failFast | false | false の場合、接続リクエストは失敗する前に maxWait まで待機します。エラーに敏感な高同時実行シナリオで、待機する代わりに即時失敗を希望する場合は true に設定します。これは通常、maxWaitThreadCount と組み合わせて使用されます。 |
timeBetweenEvictionRunsMillis | 60,000 | プールが minEvictableIdleTimeMillis に対してアイドル接続をチェックする間隔 (ミリ秒)。デフォルトはほとんどのワークロードに適しています。 |
データベース操作
一般的なデータベース操作を DruidPoolDemo クラスで実行するため、以下のメソッドを追加します。対象テーブルは sql_table_test です。
テーブルの作成
String tableName = "sql_table_test";
public void createTable() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement()) {
String sql = "create table if not exists " + tableName
+ "(id VARCHAR(255), name VARCHAR(255), PRIMARY KEY (id))";
int ret = statement.executeUpdate(sql);
System.out.println(ret);
}
}
}データの挿入
public void insertData() {
try (Connection connection = dataSource.getConnection()) {
String sql = "insert into " + tableName + "(id,name) values(?,?)";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.setString(2, "bb");
int ret = ps.executeUpdate();
System.out.println(ret);
}
} catch (SQLException e) {
e.printStackTrace();
}
}データの照会
public void selectData() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
String sql = "select * from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id=" + id);
System.out.println("name=" + name);
}
}
}
}データの削除
public void deleteData() {
try (Connection connection = dataSource.getConnection()) {
String sql = "delete from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
}次のステップ
DBUtils を使用して ApsaraDB RDS for MySQL インスタンスに接続する — Python 接続プール
Go-MySQL-Driver を使用して ApsaraDB RDS for MySQL インスタンスに接続する — Go ドライパッケージ
コネクションプーリング機能を設定する — ApsaraDB RDS データベースプロキシによるサーバー側コネクションプーリング