【Java】S3で503エラー発生?!同じプレフィックスのオブジェクトを何度もアップロードすると503エラーが発生するよ!

Amazon S3でプレフィックスが同じオブジェクトを何度もPUT(アップロード)することで503エラーが発生することは、特定の状況で起こり得ます


1. プレフィックスが同じオブジェクトを何度もPUTすることによる影響

1. ホットパーティショニング

S3では、オブジェクトキー(プレフィックスを含む)に基づいてデータがパーティショニングされます

同じプレフィックスを持つオブジェクトに対して大量のリクエストを発生させると、その特定のパーティションに負荷が集中し、「ホットパーティショニング」が発生する可能性があります

これにより、503エラーなどのリクエスト失敗が発生することがあります

2. スロットリング制限

S3の内部スロットリング機能によって、一度に受け付けるリクエスト数に制限がかけられることがあります

プレフィックスが同じオブジェクトへの頻繁なアクセスがこれに該当する場合、503エラーが発生することがあります


2. 解決方法

オブジェクトキーの分散とリトライロジックで解決していこう!

以下はサンプル実装になります

import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.io.File;
import java.nio.file.Paths;
import java.util.UUID;

public class S3Uploader {

    private static final int MAX_RETRIES = 5;
    private static final Region REGION = Region.US_EAST_1; // 適切なリージョンを設定してください
    private static final S3Client s3 = S3Client.builder()
            .region(REGION)
            .credentialsProvider(ProfileCredentialsProvider.create())
            .build();

    public static void main(String[] args) {
        String filePath = "path/to/file.jpg";
        String bucketName = "your-bucket-name";
        String prefix = "images";
        String fileName = "file.jpg";

        uploadFileWithRetries(filePath, bucketName, prefix, fileName);
    }

    private static void uploadFileWithRetries(String filePath, String bucketName, String prefix, String fileName) {
        String uniqueKey = generateUniqueKey(prefix, fileName);
        int retries = 0;
        while (retries < MAX_RETRIES) {
            try {
                PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                        .bucket(bucketName)
                        .key(uniqueKey)
                        .build();
                s3.putObject(putObjectRequest, Paths.get(filePath));
                System.out.println("File " + filePath + " uploaded successfully as " + uniqueKey);
                return;
            } catch (S3Exception e) {
                if (e.statusCode() == 503) {
                    retries++;
                    long waitTime = (long) Math.pow(2, retries);
                    System.out.println("503 Service Unavailable. Retrying in " + waitTime + " seconds...");
                    try {
                        Thread.sleep(waitTime * 1000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        System.err.println("Thread interrupted: " + ie.getMessage());
                    }
                } else {
                    System.err.println("Failed to upload file: " + e.awsErrorDetails().errorMessage());
                    return;
                }
            }
        }
        System.out.println("Max retries reached. File upload failed.");
    }

    private static String generateUniqueKey(String prefix, String filename) {
        String uniqueId = UUID.randomUUID().toString();
        return String.format("%s/%s-%s", prefix, uniqueId, filename);
    }
}

説明

  1. S3クライアントの設定:S3Clientを使用してS3クライアントを設定します。適切なリージョンと認証情報を使用してください。
  2. オブジェクトキーの生成:generateUniqueKeyメソッドで、UUIDを使用して一意のオブジェクトキーを生成します
  3. リトライロジックの実装:uploadFileWithRetriesメソッドで、503エラーが発生した場合にエクスポネンシャルバックオフを使用してリトライします

是非ご参考くださいませ!

是非フォローしてください

最新の情報をお伝えします