ApsaraMQ for RabbitMQ は、インスタンスごとに TPS 制限を適用し、しきい値を超えたチャネルを閉じます。本ガイドでは、予防、監視、およびエラー復旧について説明します。
スロットリングの仕組み
ApsaraMQ for RabbitMQ は、3 つのレベルで TPS 制限を適用します。
インスタンス合計 TPS:インスタンス全体の送信と受信を合わせたスループットに上限を設定します。
単一ノード SendMessage TPS:クラスター内の各バックエンドサービスノードの送信スループットに上限を設定します。
API 操作ごとの TPS:
basicGet、queueDeclare、exchangeDeclareなどの特定の操作に上限を設定します。
いずれかの制限を超えた場合、ブローカーは以下の動作をします。
ブローカーは
reply-code=530とreply-text=denied for too many requestsを返します。エラーの詳細については、「エラーコードとメッセージ」をご参照ください。ブローカーは、リクエストを送信した チャネルを閉じます。接続は開いたままです。チャネルを再オープンすることによる復旧については、「チャネル閉鎖からの復旧」をご参照ください。
スロットリングの防止
インスタンス合計 TPS
トラフィックパターンに合わせて以下のアプローチを選択してください。
トラフィックパターン | 対応策 |
テスト、短期間、または予測不可能なトラフィック | サーバーレスインスタンスを使用してください。サブスクリプションインスタンスの場合は、エラスティック TPS 機能を有効化してください。 |
安定した大量の本番トラフィック | TPS 仕様をアップグレードして、より高いティアに移行してください。 |
単一ノード SendMessage TPS
ApsaraMQ for RabbitMQ は、複数のバックエンドノードにトラフィックを分散します。トラフィックが 1 つのノードに集中すると、インスタンスレベルの制限に余裕があっても、ノードごとの制限が発動します。
ノード間に負荷を均等に分散するには、以下の対策を実施してください。
キューごとに少なくとも 10 個の接続を開きます。各接続は異なるノードにルーティングされる可能性があり、送信ワークロードが分散されます。
Spring ユーザーの場合は、
CachingConnectionFactoryを CONNECTION モードに設定してください。これにより、1 つの接続でチャネルを多重化するのではなく、セッションごとに新しい接続が作成されます。詳細については、「Spring 統合」をご参照ください。
ピーク TPS の監視
ピーク TPS を監視し、トラフィックがスロットリングしきい値に近づいたタイミングを検出してください。
CloudMonitor (推奨)
粒度:分レベル (1 分間隔)
範囲:インスタンスレベルのピーク TPS
コスト:無料
過去 14 日間の TPS トレンドを表示します。
スロットリング発生前に通知するアラートルールをサポートします。
詳細については、「CloudMonitor を使用したインスタンスのピーク TPS のクエリとアラートルールの設定」をご参照ください。
インスタンス詳細ページ (推奨)
粒度:秒レベルのピーク TPS
範囲:インスタンスレベルおよび API 操作ごとのピーク TPS
コスト:無料
秒レベルの精度で短時間のトラフィックスパイクを特定します。
API 操作ごとのフィルタリングをサポートします。
最初の 10 分間の結果のみが表示されます。
詳細については、「インスタンス詳細ページでのインスタンスのピーク TPS のクエリ」をご参照ください。
Simple Log Service
粒度:秒レベルのピーク TPS
範囲:インスタンスレベルのピーク TPS
コスト:Simple Log Service による課金 (詳細については、「従量課金の課金項目」をご参照ください)
高度な分析のための SLS クエリステートメントをサポートします。
SLS クエリ構文の知識が必要です。CloudMonitor やインスタンス詳細ページと比較すると、結果の解釈が難しい場合があります。
詳細については、「Simple Log Service を使用したインスタンスのピーク TPS のクエリ」をご参照ください。
スロットリングしきい値
以下の表に、インスタンスタイプおよび仕様ごとのスロットリング制限を示します。
インスタンス合計 TPS
サーバーレスインスタンス
クラスタータイプ | 課金モデル | スロットリングしきい値 |
共有クラスター | プロビジョニング済み容量とエラスティックトラフィックによる課金 / メッセージングリクエストによる課金 | 最大:50,000 TPS |
専用クラスター | プロビジョニング済み容量とエラスティックトラフィックによる課金 | 基本仕様に含まれるピーク TPS の 2 倍 |
サブスクリプションインスタンス
エディション | エラスティック TPS | スロットリングしきい値 |
Enterprise Edition | 無効 | 基本仕様に含まれるピーク TPS |
Enterprise Edition | 有効 | 基本仕様に含まれるピーク TPS の 2 倍 (最大:50,000 TPS) |
Enterprise Platinum Edition | 無効 | 基本仕様に含まれるピーク TPS |
Enterprise Platinum Edition | 有効 | 基本仕様に含まれるピーク TPS の 2 倍 (最大:50,000 TPS) |
Professional Edition | 無効 | 基本仕様に含まれるピーク TPS |
Professional Edition | 有効 | 基本仕様に含まれるピーク TPS の 1.5 倍 |
単一ノード SendMessage TPS
ブローカーは、インスタンス内の各バックエンドノードで SendMessage TPS を制限します。
インスタンスタイプ | スロットリングしきい値 |
サーバーレス -- 共有 (累積量による課金) | 25,000 TPS |
サーバーレス -- 専用 (予約 + エラスティック) | 25,000 TPS |
サブスクリプション -- Enterprise Edition | なし |
サブスクリプション -- Enterprise Platinum Edition | 25,000 TPS |
サブスクリプション -- Professional Edition | 25,000 TPS |
API 操作ごとの制限
これらの制限はインスタンスごとに適用されます。サーバーレス専用クラスターインスタンスには、API ごとのスロットリングはありません。
操作 | API メソッド | サーバーレス (共有) | サーバーレス (専用) | サブスクリプション |
同期メッセージ受信 |
| 500 TPS | なし | 500 TPS |
キューのクリア |
| 500 TPS | なし | 500 TPS |
Exchange の作成 |
| 500 TPS | なし | 500 TPS |
Exchange の削除 |
| 500 TPS | なし | 500 TPS |
キューの作成 |
| 500 TPS | なし | 500 TPS |
キューの削除 |
| 500 TPS | なし | 500 TPS |
バインディングの作成 |
| 500 TPS | なし | 500 TPS |
バインディングの削除 |
| 500 TPS | なし | 500 TPS |
メッセージの復元 |
| 500 TPS | なし | 500 TPS |
メッセージの再キューイング |
| 20 TPS | なし | 20 TPS |
スロットリングエラーの処理
エラーコードとメッセージ
スロットリングが発動すると、ブローカーは影響を受けたチャネルを閉じ、以下を返します。
エラーコード:
reply-code=530エラーメッセージ:
reply-text=denied for too many requests
エラーには、リクエスト ID (ReqId)、宛先キュー (dstQueue)、送信元 Exchange (srcExchange)、およびバインディングキー (bindingKey) が含まれます。
チャネル閉鎖からの復旧
チャネルのみが閉じられるため、AlreadyClosedException をキャッチして再作成してください。以下の Java サンプルは、リトライによる復旧を示しています。
private static final int MAX_RETRIES = 5; // 最大リトライ試行回数
private static final long WAIT_TIME_MS = 2000; // リトライ間の待機時間 (ミリ秒)
private void doAnythingWithReopenChannels(Connection connection, Channel channel) {
try {
// ......
// 現在のチャネルで実行する任意の操作。
// 例: メッセージの送信または消費。
// ......
} catch (AlreadyClosedException e) {
String message = e.getMessage();
if (isChannelClosed(message)) {
// チャネルがブローカーによって閉じられました。再作成します。
channel = createChannelWithRetry(connection);
// 復旧後、他の操作を続行します。
// ......
} else {
throw e;
}
}
}
private Channel createChannelWithRetry(Connection connection) {
for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
return connection.createChannel();
} catch (Exception e) {
System.err.println("チャネルの作成に失敗しました。試行 " + attempt + " / " + MAX_RETRIES);
// チャネル作成が失敗した場合 (おそらくまだスロットリング中)、待機してリトライします。
if (attempt < MAX_RETRIES) {
try {
Thread.sleep(WAIT_TIME_MS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // 割り込み状態を復元します。
}
} else {
throw new RuntimeException("チャネル作成の最大リトライ回数を超えました", e);
}
}
}
throw new RuntimeException("この行には到達しないはずです");
}
private boolean isChannelClosed(String errorMsg) {
// エラーメッセージに "channel.close" が含まれているかどうかを確認します。
// これは、エラーコード 530 (スロットリング) と 541 (内部エラー) の両方をカバーします。
if (errorMsg != null && errorMsg.contains("channel.close")) {
System.out.println("[ChannelClosed] エラー詳細: " + errorMsg);
return true;
}
return false;
}重要なポイント:
リトライでは固定の 2,000 ミリ秒の待機時間を使用しています。トラフィックパターンに応じて調整してください。
isChannelClosedメソッドは、エラーメッセージ内のchannel.closeをチェックします。これは、reply-code=530(スロットリング) およびその他のチャネル閉鎖シナリオの両方をカバーします。復旧後、新しいチャネルオブジェクトで操作を再開してください。