1. ホーム
  2. java

[解決済み] AmazonS3ClientBuilder.defaultClient()がリージョンを考慮できていない?

2022-02-04 20:27:35

質問

Amazon Java SDK は、以下のコンストラクタをマークしています。 AmazonS3Client を採用したため、非推奨となりました。 AmazonS3ClientBuilder.defaultClient() . しかし、この勧告に従ったとしても、同じように動作するAmazonS3クライアントができるわけではありません。 特に、このクライアントでは、なぜかRegionを考慮できていません。 以下のテストを実行すると thisFails のテストは、この問題を実証しています。

public class S3HelperTest {
  @Test
  public void thisWorks() throws Exception {
    AmazonS3 s3Client = new AmazonS3Client();  // this call is deprecated
    s3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
    assertNotNull(s3Client);
  }

  @Test
  public void thisFails() throws Exception {
    AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
    /*
     * The following line throws like com.amazonaws.SdkClientException:
     * Unable to find a region via the region provider chain. Must provide an explicit region in the builder or
     * setup environment to supply a region.
     */
    s3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
  }
}

com.amazonaws.SdkClientException: Unable to find a region via the region provider chain. Must provide an explicit region in the builder or setup environment to supply a region.
    at com.amazonaws.client.builder.AwsClientBuilder.setRegion(AwsClientBuilder.java:371)
    at com.amazonaws.client.builder.AwsClientBuilder.configureMutableProperties(AwsClientBuilder.java:337)
    at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
    at com.amazonaws.services.s3.AmazonS3ClientBuilder.defaultClient(AmazonS3ClientBuilder.java:54)
    at com.climate.tenderfoot.service.S3HelperTest.thisFails(S3HelperTest.java:21)
    ...

これはAWS SDKのバグでしょうか? リージョンデフォルトのプロバイダチェーンとか、環境からリージョンを派生させてクライアントに設定する仕組みとかあるんでしょうか? 非推奨を置き換える方法で同じ機能にならないのは本当に弱い気がします。

解決方法は?

ビルダーにはリージョンが必要なようです。 おそらく このスレッド が関連しています(私なら .withRegion(Regions.US_EAST_1) ただし、3行目)。

以前の動作(リージョンが設定されていない)をエミュレートするには を有効にすると、クライアントビルダーで "forced global bucket access" も有効になります。

AmazonS3 client = 
        AmazonS3ClientBuilder.standard()
                             .withRegion("us-east-1") // The first region to try your request against
                             .withForceGlobalBucketAccess(true) // If a bucket is in a different region, try again in the correct region
                             .build();

これにより、受け取った例外が抑制され、自動的に再試行されます。 例外に含まれる地域の下でリクエストを行う。で明示されています。 ビルダーは、このクロスリージョンの挙動を認識できるようにします。注意: ビルダーは SDKは、最初の失敗の後、バケットリージョンをキャッシュします。 このバケツに対するすべてのリクエストは、2度行われる必要はありません。


また AWSのドキュメント を使用する場合 AmazonS3ClientBuilder.defaultClient(); が必要です。 ~/.aws/credentials および ~/.aws/config ファイル

~/.aws/credentials の内容です。

[default]
aws_access_key_id = your_id
aws_secret_access_key = your_key

~/.aws/config の内容です。

[default]
region = us-west-1


同上より AWSのドキュメント のページをご覧ください。 リージョン/クレデンシャルをハードコードしたくない場合 のように、Linuxマシンで環境変数として持つことができます。

export AWS_ACCESS_KEY_ID=your_access_key_id
export AWS_SECRET_ACCESS_KEY=your_secret_access_key
export AWS_REGION=your_aws_region