0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS ECS と SQS を活用したスケーリングと処理最適化の完全ガイド

Posted at

1. はじめに

1.1 背景

クラウドアーキテクチャにおいて、スケーラブルなアプリケーションを構築することは重要な課題です。特に、マイクロサービス環境では、柔軟にリソースを増減できる仕組みが求められます。AWS の Elastic Container Service (ECS) と Simple Queue Service (SQS) を組み合わせることで、負荷に応じたスケール調整が可能になります。

本記事では、ECS とは何か、SQS とは何かを詳しく解説し、それらを組み合わせたスケーラブルなアーキテクチャの構築方法を詳細に説明します。また、ECS タスク内の並列処理を Java を用いて実装する方法についても深く掘り下げます。

1.2 ECS と SQS を組み合わせる理由

ECS はコンテナのスケーリングと管理を担い、SQS は非同期メッセージングを提供します。この 2 つを組み合わせることで、リアルタイム処理を求められるマイクロサービスアーキテクチャや、バッチ処理を効率化するワークフローシステムなどで特に有効に機能します。例えば、EC サイトにおける注文処理では、SQS を使って決済や在庫管理のリクエストをキューイングし、ECS のスケールアウト機能を活用して、ピーク時の負荷に適応できます。同様に、データ分析基盤では、大量のログやセンサーデータを SQS で処理キューに格納し、ECS を使って並列処理することで、処理の遅延を最小限に抑えることができます。この 2 つを組み合わせることで、以下のような利点があります。

  • 負荷分散の最適化: SQS を使ってリクエストをキューイングし、ECS タスクが処理可能な範囲で順次処理。
  • 高可用性の確保: ECS のスケールアウト/イン機能と SQS の耐障害性を活かし、システム全体の安定性を向上。
  • コスト最適化: 必要な分だけリソースを使用し、不要になればスケールイン。

2. ECS とは?

2.1 ECS の概要

AWS Elastic Container Service (ECS) は、Docker コンテナを簡単にデプロイ・管理できるフルマネージドなコンテナオーケストレーションサービスです。

2.2 ECS の特徴

  • マネージドサービス: Kubernetes のようなクラスタ管理が不要。
  • Fargate 対応: インフラ管理なしでコンテナを実行可能。
  • 自動スケーリング: 負荷に応じてコンテナ数を増減可能。
  • IAM 権限管理: コンテナごとに異なる IAM ポリシーを適用可能。

2.3 ECS のコンポーネント

  • クラスター: コンテナを実行する環境。
  • タスク定義: コンテナの設定(CPU、メモリ、環境変数など)。
  • サービス: タスクの管理(スケーリング、ヘルスチェック)。
  • タスク: 実行中のコンテナ。
  • ロードバランサー: コンテナの負荷分散を管理。
  • オートスケール: 負荷に応じて ECS タスクを自動で増減。

3. SQS とは?

3.1 SQS の概要

AWS Simple Queue Service (SQS) は、メッセージを非同期で送受信できるフルマネージドなメッセージキューサービスです。ECS などの処理システムと組み合わせることで、システムの耐障害性を向上させることができます。

3.2 SQS の特徴

  • 非同期処理: 処理をキューに蓄積し、適切なタイミングで処理可能。
  • 自動スケーリング: メッセージ量に応じたスケーリングが可能。
  • 高可用性: AWS によってフルマネージドされているため、障害耐性が高い。
  • 高スループット: 大量のメッセージ処理に最適。

3.3 SQS の種類

  • 標準キュー: 高スループット、メッセージの順序保証なし。
  • FIFO キュー: メッセージの順序を保証、重複処理を防ぐ。
  • デッドレターキュー (DLQ): 処理失敗メッセージを蓄積し、手動で再処理可能。

4. ECS タスク内の並列処理 (Java)

ECS タスク内の処理を効率化するために、Java の FixedThreadPool を利用して並列処理を行う方法を紹介します。

4.1 Java による並列処理の実装

private final ExecutorService service = Executors.newFixedThreadPool(3);

4.2 並列タスクの処理

ECS タスク内でメッセージを並列に処理するために、FixedThreadPool を使用して複数のスレッドを作成します。以下のコードは、SQS からメッセージを取得し、並列で処理する実装例です。

import java.util.concurrent.*;
import java.util.List;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;

public class SqsMessageProcessor {
    private final ExecutorService service = Executors.newFixedThreadPool(3);
    private final SqsClient sqsClient;
    private final String queueUrl;

    public SqsMessageProcessor(SqsClient sqsClient, String queueUrl) {
        this.sqsClient = sqsClient;
        this.queueUrl = queueUrl;
    }

    public void processMessages() {
        while (true) {
            List<Message> messages = receiveMessages();
            if (messages.isEmpty()) continue;

            for (Message message : messages) {
                service.submit(() -> handleMessage(message));
            }
        }
    }

    private List<Message> receiveMessages() {
        ReceiveMessageRequest request = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .maxNumberOfMessages(10)
                .waitTimeSeconds(10)
                .build();
        
        return sqsClient.receiveMessage(request).messages();
    }

    private void handleMessage(Message message) {
        try {
            System.out.println("Processing message: " + message.body());
            Thread.sleep(5000); // 模擬的な処理
            deleteMessage(message);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    private void deleteMessage(Message message) {
        DeleteMessageRequest deleteRequest = DeleteMessageRequest.builder()
                .queueUrl(queueUrl)
                .receiptHandle(message.receiptHandle())
                .build();
        sqsClient.deleteMessage(deleteRequest);
    }

    public void shutdown() {
        service.shutdown();
        try {
            if (!service.awaitTermination(60, TimeUnit.SECONDS)) {
                service.shutdownNow();
            }
        } catch (InterruptedException e) {
            service.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

4.3 Graceful Shutdown の実装

ECS のタスクが停止される際に、安全にスレッドを終了させるための ShutdownHook を追加します。

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    System.out.println("Shutting down gracefully...");
    service.shutdown();
    try {
        if (!service.awaitTermination(60, TimeUnit.SECONDS)) {
            service.shutdownNow();
        }
    } catch (InterruptedException e) {
        service.shutdownNow();
    }
}));

このコードにより、ECS のタスクが SIGTERM を受信した際に、並列処理中のタスクを適切に処理しつつ、安全にシャットダウンすることができます。


5. SQS のメッセージ処理最適化

SQS の設定を最適化することで、処理の効率化とリソースの適切な使用を実現できます。特に、可視性タイムアウト(Visibility Timeout)や最大受信メッセージ数(MaxNumberOfMessages)の設定は、システムのパフォーマンスに大きく影響を与えます。

可視性タイムアウトの最適な設定

可視性タイムアウトは、ECS タスクがメッセージを取得した後、他のコンシューマーが同じメッセージを取得できないようにする時間です。処理時間が短すぎると、まだ処理が完了していないメッセージが再取得され、重複処理が発生する可能性があります。

メッセージ処理時間 推奨可視性タイムアウト
5 秒未満 15 秒
10 秒 25 秒
30 秒 60 秒
60 秒以上 処理時間の 2 倍

適切な値を設定することで、メッセージの二重処理を防ぎつつ、ECS の処理負荷を最適化できます。

最大受信メッセージ数の設定

MaxNumberOfMessages は、一度に取得するメッセージ数を指定します。ECS のスレッド数に応じて適切な値を設定すると、処理効率が向上します。

ECS のスレッド数 推奨 MaxNumberOfMessages
1 1
2 2 ~ 5
3 3 ~ 7
4 4 ~ 8
5 以上 5 ~ 10

最大 10 件まで設定可能ですが、すべてのメッセージを処理し終える前にタイムアウトすると、未処理メッセージが残る可能性があるため注意が必要です。

メッセージ再試行とデッドレターキューの活用

処理に失敗したメッセージが無限にリトライされないように、デッドレターキュー(DLQ)を設定すると、エラーメッセージを安全に管理できます。通常、MaximumReceives を 5 ~ 10 に設定し、特定回数以上失敗したメッセージを DLQ に移動させることで、システムの安定性を向上できます。

このように、SQS の設定を適切に調整することで、ECS のパフォーマンスを最大限に引き出し、安定したメッセージ処理システムを構築できます。


6. ECS のスケールイン・スケールアウトの仕組み

ECS のスケーリングに関する詳細な説明と、AWS Auto Scaling の設定方法を解説します。

6.1 オートスケーリングの設定例

ECS では Application Auto Scaling を使用して、タスク数を自動的に増減できます。オートスケーリングを設定するには、次のステップを実行します。

ステップ 1: スケーラブルターゲットの作成

aws application-autoscaling register-scalable-target \
    --service-namespace ecs \
    --scalable-dimension ecs:service:DesiredCount \
    --resource-id service/my-cluster/my-service \
    --min-capacity 1 \
    --max-capacity 10

このコマンドは、ECS サービス my-service のタスク数を 1~10 の範囲でスケール 可能にします。

ステップ 2: スケーリングポリシーの作成

aws application-autoscaling put-scaling-policy \
    --service-namespace ecs \
    --scalable-dimension ecs:service:DesiredCount \
    --resource-id service/my-cluster/my-service \
    --policy-name ecs-scale-out-policy \
    --policy-type TargetTrackingScaling \
    --target-tracking-scaling-policy-configuration file://scale-out.json

ここで scale-out.json は、CPU 使用率や SQS のメトリクスを基準にスケールするための JSON 設定ファイルです。

scale-out.json の例 (CPU 使用率 70% でスケールアウト)

{
  "TargetValue": 70.0,
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
  },
  "ScaleOutCooldown": 60,
  "ScaleInCooldown": 300
}

6.2 監視すべきメトリクス

ECS のスケーリングには、以下のメトリクスを活用できます。

メトリクス 説明 推奨トリガー
ECSServiceAverageCPUUtilization ECS タスクの平均 CPU 使用率 70% 以上でスケールアウト
ECSServiceAverageMemoryUtilization ECS タスクの平均メモリ使用率 75% 以上でスケールアウト
ApproximateNumberOfMessagesVisible SQS に残っている未処理メッセージ数 10 件以上でスケールアウト

これらの設定を活用することで、負荷に応じた効率的なオートスケーリングを実現できます。


7. まとめ

本記事では、AWS ECS と SQS を活用したスケーラブルなアーキテクチャの構築方法を解説しました。

ECS と SQS を組み合わせてスケールしやすいシステムを構築
ECS の stopTimeout を適切に設定し、Graceful Shutdown を確保
ECS 内で Java を用いた並列処理を実装し、スループットを向上

これらのベストプラクティスを活用し、スケーラブルで高効率な AWS インフラを構築しましょう! 🚀

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?