ApsaraMQ for RocketMQ には、プッシュコンシューマーとシンプルコンシューマーの 2 種類のコンシューマーが用意されています。各タイプは、メッセージの取得方法、同時実行数、リトライ処理をそれぞれ異なる方法で実現します。ご自身の処理モデルおよび信頼性要件に合ったタイプを選択してください。
コンシューマータイプの選択
| シナリオ | 推奨タイプ | 理由 |
|---|---|---|
| 処理時間が予測可能で、カスタムスレッド管理を行わない場合 | プッシュコンシューマー | SDK がメッセージのフェッチ、同時実行数、リトライを管理します。リスナーを登録し、各メッセージを処理して結果を返すだけです。 |
| 処理時間が可変で、カスタムワークフローが必要な場合 | シンプルコンシューマー | アプリケーション側でメッセージのフェッチタイミング、スレッド間でのディストリビューション方法、完了の通知タイミングを制御できます。 |
コンシューマータイプを切り替えても、既存の ApsaraMQ for RocketMQ リソースやビジネスプロセスには影響しません。
メッセージ処理のステージ
どちらのコンシューマータイプも、以下の 3 ステージのライフサイクルに従います。
受信 — サーバーからメッセージをフェッチします。
処理 — 各メッセージに対してビジネスロジックを実行します。
コミット — サーバーに処理結果(成功または失敗)を報告します。

両タイプは、各ステージの処理方法が異なります。
| 機能 | プッシュコンシューマー | シンプルコンシューマー |
|---|---|---|
| インターフェース | リスナーコールバック — リスナー内でロジックを実装し、結果を返します | アプリケーションが API オペレーションを呼び出して、メッセージの受信、処理、確認応答を行います |
| 同時実行 | SDK が管理 | アプリケーションが管理 |
| 柔軟性 | 高度にカプセル化されており、柔軟性は低め | アトミックな操作で、高度にカスタマイズ可能 |
| 最適な用途 | 処理時間が予測可能な標準的な消費処理 | カスタムワークフロー、非同期ディストリビューション、バッチ消費処理 |
| SDK クラス | PushConsumer、LitePushConsumer | SimpleConsumer |
プッシュコンシューマー
プッシュコンシューマーは、メッセージのフェッチ、スレッド管理、リトライロジックをカプセル化しています。初期化時にメッセージリスナーを登録すると、以降の処理は SDK が自動で行います。
仕組み
SDK は内部で Reactor スレッドモデルを使用します。
組み込みのロングポーリングスレッドが、非同期にサーバーからメッセージをプルします。
メッセージは内部のキャッシュキューに格納されます。
SDK がコンシューマースレッドにメッセージをディスパッチし、リスナーを呼び出します。

リスナーの結果
メッセージリスナーは、以下のいずれかの結果を返す必要があります。
| 結果 | Java SDK 定数 | 動作 |
|---|---|---|
| 成功 | ConsumeResult.SUCCESS | サーバーが消費進捗を更新します。 |
| 失敗 | ConsumeResult.FAILURE | プッシュコンシューマーのリトライポリシーに基づいてシステムが再試行します。 |
| 例外がスローされた場合 | (失敗として扱われる) | 明示的な失敗と同じリトライ動作になります。 |
タイムアウト時の動作
処理ロジックがブロックされ、許容時間内にメッセージ処理が完了しない場合、SDK は強制的に失敗結果を送信し、リトライポリシーに従ってメッセージを処理します。
タイムアウトにより SDK が失敗結果を送信しますが、現在の処理スレッドは割り込みに応答せず、引き続き実行を続ける可能性があります。
信頼性に関する制約
プッシュコンシューマーは、リスナーの戻り値のみに基づいて成功または失敗を厳密に判断します。この保証を維持するため、以下の点に注意してください。
同期的に処理する。 結果を返す前に、すべての処理を完了させてください。
メッセージを再配布しない。 メッセージを他のスレッドに渡して、それらのスレッドが完了する前に結果を返さないでください。
リスナーが処理完了前に成功を返し、その後処理が失敗した場合、サーバーはそのメッセージを正常に消費されたものと見なし、再試行を行いません。
順序付きメッセージの配信
コンシューマーグループが順序付き消費モードを使用している場合、プッシュコンシューマーは追加の構成なしに、厳密なメッセージ順序でリスナーを呼び出します。詳細については、「順序付きメッセージ」をご参照ください。
順序付き配信には同期的処理が必要です。リスナー内でカスタムの非同期ディストリビューションを行うと、順序保証が無効になります。
プッシュコンシューマーの適用範囲
プッシュコンシューマーは、以下の条件を満たす場合に最適です。
処理時間が予測可能である。 処理時間が予測できないと頻繁にタイムアウトが発生し、リトライによって重複メッセージが発生します。
標準的な消費処理で十分である。 SDK がスレッドモデルを制御し、最大スループットでメッセージを配信します。これにより開発が簡素化されますが、非同期処理やカスタムレート制御はサポートされません。
SDK クラス
ApsaraMQ for RocketMQ では、プッシュコンシューマー向けに以下の 2 つの SDK クラスを提供しています。
PushConsumer— 標準(Lite 以外)トピックからのメッセージを消費します。LitePushConsumer— Lite タイプのトピックからのメッセージを消費し、Lite トピック単位で消費制御を行います。
PushConsumer の例
// PushConsumer を使用して通常メッセージを消費します
ClientServiceProvider provider = ClientServiceProvider.loadService();
String topic = "<your-topic>";
FilterExpression filterExpression = new FilterExpression("<your-filter-tag>", FilterExpressionType.TAG);
PushConsumer pushConsumer = provider.newPushConsumerBuilder()
// コンシューマーグループを設定します
.setConsumerGroup("<your-consumer-group>")
// アクセスエンドポイントを設定します
.setClientConfiguration(ClientConfiguration.newBuilder().setEndpoints("<your-endpoint>").build())
// サブスクリプションをバインドします
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
// メッセージリスナーを登録します
.setMessageListener(new MessageListener() {
@Override
public ConsumeResult consume(MessageView messageView) {
// メッセージを処理し、結果を返します
return ConsumeResult.SUCCESS;
}
})
.build();以下のプレースホルダーを実際の値に置き換えてください。
| プレースホルダー | 説明 | 例 |
|---|---|---|
<your-topic> | トピック名 | order-events |
<your-filter-tag> | フィルタリング用のメッセージタグ | payment |
<your-consumer-group> | コンシューマーグループ名 | order-service-group |
<your-endpoint> | サーバーアクセスエンドポイント | -- |
LitePushConsumer の例
// LitePushConsumer を使用して通常メッセージを消費します
ClientServiceProvider provider = ClientServiceProvider.loadService();
LitePushConsumer litePushConsumer = provider.newLitePushConsumerBuilder()
// アクセスエンドポイントを設定します
.setClientConfiguration(ClientConfiguration.newBuilder().setEndpoints("<your-endpoint>").build())
// トピックを設定します
.bindTopic("<your-topic>")
// コンシューマーグループを設定します
.setConsumerGroup("<your-consumer-group>")
// メッセージリスナーを登録します
.setMessageListener(messageView -> {
// メッセージを処理し、結果を返します
return ConsumeResult.SUCCESS;
})
.build();
// Lite トピックをサブスクライブします
litePushConsumer.subscribeLite("<your-lite-topic-1>");
litePushConsumer.subscribeLite("<your-lite-topic-2>");シンプルコンシューマー
シンプルコンシューマーは、メッセージ処理のためのアトミックな API オペレーションを提供します。アプリケーション側で、メッセージのフェッチ、スレッド管理、確認応答を直接制御できます。
仕組み
ReceiveMessageを呼び出して、サーバーからメッセージのバッチをプルします。メッセージをビジネススレッドにディストリビュートして処理します。
正常に処理された各メッセージに対して
AckMessageを呼び出します。
処理が失敗した場合は、確認応答を送信しないでください。メッセージの非表示期間が終了すると、メッセージは再度利用可能になり、リトライがトリガーされます。詳細については、「シンプルコンシューマーのリトライポリシー」をご参照ください。
API オペレーション
| オペレーション | 目的 | 主なパラメーター |
|---|---|---|
ReceiveMessage | サーバーからメッセージをプルする | バッチサイズ: 1 回のリクエストあたりのメッセージ数。メッセージ非表示期間: メッセージが再配信されるまでの最大処理時間。 |
AckMessage | 正常な消費を確認応答する | なし |
ChangeInvisibleDuration | すでに受信済みのメッセージの処理時間を延長する | メッセージ非表示期間: 新しい値。通常、処理に当初の想定より時間がかかる場合に使用します。 |
サーバーは分散ストレージを使用しているため、メッセージが存在していても ReceiveMessage が空の結果を返すことがあります。これを回避するには、ReceiveMessage を再度呼び出すか、呼び出しの同時実行数を増やしてください。
障害時の処理
以下の表は、さまざまな障害シナリオがメッセージ配信に与える影響を示しています。
| 障害シナリオ | 動作 |
|---|---|
| 処理が失敗(ACK 未送信) | 非表示期間が終了すると、メッセージが再度表示され、サーバーが再配信してリトライを実行します。 |
| 処理が非表示期間を超えた | ACK 未送信時と同じ動作 — メッセージが再度表示され、再配信されます。ChangeInvisibleDuration を使用して、非表示期間が終了する前に処理ウィンドウを延長できます。 |
| ACK 送信前にコンシューマーがクラッシュ | 非表示期間が終了すると、メッセージが再配信されます。 |
順序付きメッセージの配信
シンプルコンシューマーは、順序付きメッセージをストレージ順に処理します。シーケンスを維持する必要のあるメッセージグループでは、先行メッセージの処理が完了するまで次のメッセージを取得できません。
シンプルコンシューマーの適用範囲
シンプルコンシューマーは、以下の条件を満たす場合に最適です。
処理時間が予測不可能である。
ReceiveMessage呼び出し時に初期のメッセージ非表示期間を指定し、必要に応じてChangeInvisibleDurationで延長できます。カスタムワークフローが必要である。 SDK はスレッドモデルを強制しないため、非同期ディストリビューション、バッチ消費、任意のカスタムパターンを実装できます。
レート制御が重要である。 アプリケーションコードが
ReceiveMessageを呼び出すタイミングと頻度を決定するため、スループットを直接制御できます。
SDK クラス
ApsaraMQ for RocketMQ では、シンプルコンシューマー向けに SimpleConsumer という 1 つの SDK クラスを提供しています。このクラスは、Lite トピックからのメッセージを消費することはできません。
SimpleConsumer の例
// SimpleConsumer を使用して通常メッセージを消費します
ClientServiceProvider provider = ClientServiceProvider.loadService();
String topic = "<your-topic>";
FilterExpression filterExpression = new FilterExpression("<your-filter-tag>", FilterExpressionType.TAG);
SimpleConsumer simpleConsumer = provider.newSimpleConsumerBuilder()
// コンシューマーグループを設定します
.setConsumerGroup("<your-consumer-group>")
// アクセスエンドポイントを設定します
.setClientConfiguration(ClientConfiguration.newBuilder().setEndpoints("<your-endpoint>").build())
// サブスクリプションをバインドします
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
.build();
try {
// 最大 10 件のメッセージをプルし、最大 30 秒待機します
List<MessageView> messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30));
messageViewList.forEach(messageView -> {
System.out.println(messageView);
// 正常に処理された各メッセージを確認応答します
try {
simpleConsumer.ack(messageView);
} catch (ClientException e) {
e.printStackTrace();
}
});
} catch (ClientException e) {
// スロットリングなどの障害を処理し、receive 呼び出しを再試行します
e.printStackTrace();
}ベストプラクティス
プッシュコンシューマーの処理時間制御
メッセージ処理をタイムアウトしきい値内に収めてください。頻繁なタイムアウトは不要なリトライと重複メッセージを引き起こします。アプリケーションで長時間実行タスクを定期的に処理する場合は、シンプルコンシューマーに切り替えて、適切なメッセージ非表示期間を設定してください。
LitePullConsumer から SimpleConsumer への移行
LitePullConsumer は、Apache RocketMQ 4.x Remoting SDK におけるコンシューマータイプでした。5.x gRPC SDK では削除されており、Go、Java、Python の 5.x SDK ではこのタイプは提供されていません。
以前、プルベースの消費処理に LitePullConsumer を使用していた場合は、5.x SDK へのアップグレード後に SimpleConsumer へ移行してください。SimpleConsumer は以下のオペレーションを提供します。
ReceiveMessage:オンデマンドでサーバーからメッセージをプルします。AckMessage:正常な消費を確認応答します。ChangeInvisibleDuration:メッセージ非表示期間を変更して、リトライ間隔を制御します。
Go SDK では、対応するメソッドは Receive および Ack です。Java SDK では、対応するメソッドは receive および ack です。