Javaにおけるキューベース負荷平準化パターン:スケーラブルなパフォーマンスのためのワークロードのバランス調整
別名
- 負荷平準化
- メッセージキューイング
キューベース負荷平準化デザインパターンの意図
キューベース負荷平準化パターンは、Javaでシステム負荷分散を巧みに管理します。キューを利用して、プロデューサーとコンシューマー間でワークロードを効率的に分散し、システムパフォーマンスとスケーラビリティを向上させます。
キューベース負荷平準化パターンの詳細な説明と実世界の例
実世界の例
実際のシナリオでは、賑やかなレストランのように、キューベース負荷平準化はシステム最適化戦略として機能し、注文は高いサービス品質と効率性を維持するために体系的にキューに入れられます。ピーク時には、すべての顧客にすぐにサービスを提供した場合、キッチンは圧倒され、待ち時間が長くなり、注文に間違いが生じる可能性があります。これを管理するために、レストランは発券機を使用してキューベースの負荷平準化システムを実装します。
顧客が注文をすると、彼らは発券番号を受け取り、注文はキューに入れられます。その後、キッチンスタッフは、受け取った順に一度に1つずつ注文を処理します。これにより、キッチンは管理可能なペースでワークロードを処理でき、過負荷を防ぎ、サービス品質を維持できます。顧客は、最も忙しい時でも注文が順番に処理され、効率的に処理されることを知って快適に待つことができます。
平易な言葉で
キューベース負荷平準化は、キューを使用してプロデューサーとコンシューマー間のワークロードを管理およびバランスを取り、システムの過負荷を防ぎ、スムーズな処理を保証するデザインパターンです。
Wikipediaによると
メッセージキューは、メッセージの受け渡しを管理するためにキューを使用するプロセス間通信(IPC)およびスレッド間通信に不可欠なコンポーネントです。これらはプロデューサーとコンシューマーを疎結合にするのに役立ち、非同期処理を可能にします。これは、キューベース負荷平準化パターンの重要な側面です。
Javaにおけるキューベース負荷平準化パターンのプログラム例
キューベース負荷平準化パターンは、システムを圧倒する可能性のある大量の散発的なタスクを管理するのに役立ちます。タスクを保持するバッファとしてキューを使用し、タスクの生成をタスク処理から切り離します。タスクは制御されたレートで処理され、最適な負荷管理と耐障害性を保証します。これは、堅牢なシステムアーキテクチャを維持するために不可欠です。
まず、MessageQueue
クラスとMessage
クラスを見てみましょう。MessageQueue
はバッファとして機能し、ServiceExecutor
によって取得されるまでメッセージを格納します。Message
は処理されるタスクを表します。
public class Message {
// Message details
}
public class MessageQueue {
private Queue<Message> queue;
public MessageQueue() {
queue = new LinkedList<>();
}
// Method to add a message to the queue
public void addMessage(Message message) {
queue.add(message);
}
// Method to retrieve a message from the queue
public Message getMessage() {
return queue.poll();
}
}
次に、TaskGenerator
クラスがあります。このクラスはタスクプロデューサーを表します。タスクを生成し、MessageQueue
に送信します。
public class TaskGenerator implements Runnable {
private MessageQueue msgQueue;
private int taskCount;
public TaskGenerator(MessageQueue msgQueue, int taskCount) {
this.msgQueue = msgQueue;
this.taskCount = taskCount;
}
@Override
public void run() {
for (int i = 0; i < taskCount; i++) {
Message message = new Message(); // Create a new message
msgQueue.addMessage(message); // Add the message to the queue
}
}
}
ServiceExecutor
クラスは、タスクコンシューマーを表します。MessageQueue
からタスクを取得し、処理します。
public class ServiceExecutor implements Runnable {
private MessageQueue msgQueue;
public ServiceExecutor(MessageQueue msgQueue) {
this.msgQueue = msgQueue;
}
@Override
public void run() {
while (true) {
Message message = msgQueue.getMessage(); // Retrieve a message from the queue
if (message != null) {
// Process the message
} else {
// No more messages to process
break;
}
}
}
}
最後に、App
クラスがあり、TaskGenerator
スレッドとServiceExecutor
スレッドを設定し、ExecutorService
に送信します。
public class App {
public static void main(String[] args) {
var msgQueue = new MessageQueue();
final var taskRunnable1 = new TaskGenerator(msgQueue, 5);
final var taskRunnable2 = new TaskGenerator(msgQueue, 1);
final var taskRunnable3 = new TaskGenerator(msgQueue, 2);
final var srvRunnable = new ServiceExecutor(msgQueue);
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(taskRunnable1);
executor.submit(taskRunnable2);
executor.submit(taskRunnable3);
executor.submit(srvRunnable);
executor.shutdown();
}
}
この例では、TaskGenerator
スレッドは可変レートでタスクを生成し、MessageQueue
に送信します。ServiceExecutor
は、キューからタスクを取得し、独自のペースで処理し、システムがピーク負荷によって圧倒されるのを防ぎます。
アプリケーションを実行すると、次のコンソール出力が生成されます
[main] INFO App - Submitting TaskGenerators and ServiceExecutor threads.
[main] INFO App - Initiating shutdown. Executor will shutdown only after all the Threads are completed.
[pool-1-thread-2] INFO TaskGenerator - Message-1 submitted by pool-1-thread-2
[pool-1-thread-1] INFO TaskGenerator - Message-5 submitted by pool-1-thread-1
[pool-1-thread-1] INFO TaskGenerator - Message-4 submitted by pool-1-thread-1
[pool-1-thread-2] INFO TaskGenerator - Message-2 submitted by pool-1-thread-2
[pool-1-thread-1] INFO TaskGenerator - Message-3 submitted by pool-1-thread-1
[pool-1-thread-2] INFO TaskGenerator - Message-1 submitted by pool-1-thread-2
[pool-1-thread-1] INFO TaskGenerator - Message-2 submitted by pool-1-thread-1
[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-2 is served.
[pool-1-thread-1] INFO TaskGenerator - Message-1 submitted by pool-1-thread-1
[pool-1-thread-2] INFO ServiceExecutor - Message-5 submitted by pool-1-thread-1 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-4 submitted by pool-1-thread-1 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-2 submitted by pool-1-thread-2 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-3 submitted by pool-1-thread-1 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-2 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-2 submitted by pool-1-thread-1 is served.
[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-1 is served.
[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve ..
[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve ..
[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve ..
[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve ..
[main] INFO App - Executor was shut down and Exiting.
[pool-1-thread-2] ERROR ServiceExecutor - sleep interrupted
Javaでキューベース負荷平準化パターンを使用する場合
- ワークロードが変動し、ピーク負荷がシステムを圧倒しないようにする必要がある場合
- タスクが消費されるレートとは異なるレートで生成される分散システムの場合
- 非同期メッセージングシステムでプロデューサーとコンシューマーを疎結合する場合
Javaにおけるキューベース負荷平準化パターンの実世界のアプリケーション
- アマゾンウェブサービス(AWS)シンプルキューサービス(SQS)
- RabbitMQ
- エンタープライズJavaアプリケーションにおけるJavaメッセージサービス(JMS)
キューベース負荷平準化パターンの利点とトレードオフ
利点
- プロデューサーとコンシューマーを疎結合にし、それぞれが独自のペースで動作できるようにします
- 過負荷状態を防ぎ、システムの回復力と耐障害性を向上させます
- 増加した負荷を処理するために、より多くのコンシューマーを追加できるようにすることで、スケーラビリティを強化します
トレードオフ
- システムアーキテクチャに複雑さを追加します
- メッセージをキューに入れてキューから取り出す必要があるため、遅延が発生する可能性があります
- 管理および監視する必要のある追加のコンポーネント(キュー)が必要です
関連するJavaデザインパターン
- 非同期メッセージング:キューベース負荷平準化は、プロデューサーとコンシューマーを疎結合するために非同期メッセージングを使用します
- サーキットブレーカー:メッセージ処理を一時的に停止することで、システムの過負荷を防ぐために、キューベース負荷平準化と組み合わせてよく使用されます
- プロデューサー・コンシューマー:キューベース負荷平準化は、キューが仲介役となるプロデューサー・コンシューマーパターンの特定のアプリケーションです
- リトライ:失敗した操作をリトライすることで、一時的な障害を処理するためにキューベース負荷平準化と連携します