

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon EC2 へのプログラムでのアクセス
<a name="ec2-api-intro"></a>

AWS マネジメントコンソール またはプログラムインターフェイスを使用して、Amazon EC2 リソースを作成および管理できます。Amazon EC2 コンソールの使用方法については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」を参照してください。

**仕組み**
+ [Amazon EC2 エンドポイント](ec2-endpoints.md)
+ [結果整合性](eventual-consistency.md)
+ [べき等性](ec2-api-idempotency.md)
+ [リクエストのスロットリング](ec2-api-throttling.md)
+ [Pagination (ページ分割](ec2-api-pagination.md)

**プログラミングインターフェイス**
+ [AWS Command Line Interface (AWS CLI)](ec2-aws-cli.md)
+ [AWS CloudFormation](ec2-cloudformation.md)
+ [AWS SDK](sdk-general-information-section.md)
+ [低レベル API](ec2-low-level-api.md)

**はじめに**
+ [コードの例](service_code_examples.md)
+ [Console-to-Code](console-to-code.md)

**モニタリング**
+ [AWS CloudTrail](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitor-with-cloudtrail.html)
+ [リクエストのモニタリング](monitor.md)

# Amazon EC2 サービスエンドポイント
<a name="ec2-endpoints"></a>

エンドポイントは、 AWS ウェブサービスのエントリポイントとして機能する URL です。Amazon EC2 は、次のエンドポイントタイプをサポートします。
+ [IPv4 エンドポイント](#ipv4)
+ [デュアルスタックエンドポイント](#ipv6) (IPv4 と IPv6 の両方をサポート)
+ [FIPS エンドポイント](https://docs.aws.amazon.com/general/latest/gr/rande.html#FIPS-endpoints)

リクエストを行うと、使用するエンドポイントを指定できます。エンドポイントを指定しない場合、デフォルトで IPv4 エンドポイントが使用されます。別のエンドポイントタイプを使用するには、リクエストで指定する必要があります。これを行う方法の例については、「[エンドポイントの指定](#examples)」を参照してください。利用可能なエンドポイントの表については、「[リージョン別のサービスエンドポイント](#service-endpoints)」を参照してください。

## IPv4 エンドポイント
<a name="ipv4"></a>

IPv4 エンドポイントは IPv4 トラフィックのみをサポートします。IPv4 エンドポイントは、すべてのリージョンで利用できます。

一般的なエンドポイントである `ec2.amazonaws.com` を指定する場合は、`us-east-1` のエンドポイントを使用します。別のリージョンを使用するには、関連するエンドポイントを指定します。例えば、`ec2.us-east-2.amazonaws.com` をエンドポイントとして指定した場合、リクエストは `us-east-2` エンドポイントに転送されます。

IPv4 エンドポイント名では、次の命名規則が使用されます。
+ `service.region.amazonaws.com`

例えば、`eu-west-1` リージョンの IPv4 エンドポイントは、`ec2.eu-west-1.amazonaws.com` です。

## デュアルスタック (IPv4 および IPv6) エンドポイント
<a name="ipv6"></a>

デュアルスタックエンドポイントは、IPv4 と IPv6 トラフィックの両方をサポートします。デュアルスタックエンドポイントにリクエストを行うと、エンドポイント URL は、ネットワークとクライアントが使用するプロトコルに応じて IPv6 または IPv4 アドレスに解決されます。

Amazon EC2 はリージョンのデュアルスタックエンドポイントのみをサポートしているため、エンドポイント名の一部としてリージョンを指定する必要があります。デュアルスタックエンドポイント名には、次の命名規則が使用されます。
+ `ec2.region.api.aws`

例えば、`eu-west-1` リージョンのデュアルスタックエンドポイント名は、`ec2.eu-west-1.api.aws` です。

## リージョン別のサービスエンドポイント
<a name="service-endpoints"></a>

Amazon EC2 のサービスエンドポイントは次のとおりです。リージョンの詳細については、「*Amazon EC2 ユーザーガイド*」の「[リージョンとアベイラビリティーゾーン](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)」を参照してください。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/ec2/latest/devguide/ec2-endpoints.html)

## エンドポイントの指定
<a name="examples"></a>

このセクションでは、リクエストを行うときにエンドポイントを指定する方法を例で示します。

------
#### [ AWS CLI ]

次の例は、 AWS CLIを使用して `us-east-2` リージョンのエンドポイントを指定する方法を示しています。
+ **デュアルスタック**

  ```
  aws ec2 describe-regions --region us-east-2 --endpoint-url https://ec2.us-east-2.api.aws
  ```
+ **IPv4**

  ```
  aws ec2 describe-regions --region us-east-2 --endpoint-url https://ec2.us-east-2.amazonaws.com
  ```

------
#### [ AWS SDK for Java 2.x ]

次の例は、 AWS SDK for Java 2.xを使用して `us-east-2` リージョンのエンドポイントを指定する方法を示しています。
+ **デュアルスタック**

  ```
  Ec2Client client = Ec2Client.builder()
      .region(Region.US_EAST_2)
      .endpointOverride(URI.create("https://ec2.us-east-2.api.aws"))
      .build();
  ```
+ **IPv4**

  ```
  Ec2Client client = Ec2Client.builder()
      .region(Region.US_EAST_2)
      .endpointOverride(URI.create("https://ec2.us-east-2.amazonaws.com"))
      .build();
  ```

------
#### [ AWS SDK for Java 1.x ]

次の例は、 AWS SDK for Java 1.x を使用して`eu-west-1`リージョンのエンドポイントを指定する方法を示しています。
+ **デュアルスタック**

  ```
  AmazonEC2 s3 = AmazonEC2ClientBuilder.standard()
       .withEndpointConfiguration(new EndpointConfiguration(
            "https://ec2.eu-west-1.api.aws",
            "eu-west-1"))
       .build();
  ```
+ **IPv4**

  ```
  AmazonEC2 s3 = AmazonEC2ClientBuilder.standard()
       .withEndpointConfiguration(new EndpointConfiguration(
            "https://ec2.eu-west-1.amazonaws.com",
            "eu-west-1"))
       .build();
  ```

------
#### [ AWS SDK for Go ]

次の例は、 AWS SDK for Goを使用して `us-east-1` リージョンのエンドポイントを指定する方法を示しています。
+ **デュアルスタック**

  ```
  sess := session.Must(session.NewSession())
  svc := ec2.New(sess, &aws.Config{
      Region: aws.String(endpoints.UsEast1RegionID),
      Endpoint: aws.String("https://ec2.us-east-1.api.aws")
  })
  ```
+ **IPv4**

  ```
  sess := session.Must(session.NewSession())
  svc := ec2.New(sess, &aws.Config{
      Region: aws.String(endpoints.UsEast1RegionID),
      Endpoint: aws.String("https://ec2.us-east-1.amazonaws.com")
  })
  ```

------

# Amazon EC2 API の結果整合性
<a name="eventual-consistency"></a>

Amazon EC2 API は、この API をサポートしているシステムの分散特性により、結果整合性モデルに従います。つまり、Amazon EC2 リソースに影響を及ぼす、実行した API コマンドの結果は、その後に実行するすべてのコマンドにすぐには表示されない可能性があります。前の API コマンドの直後に API コマンドを実行する場合は、この点に留意する必要があります。

結果整合性は、リソースの管理方法に影響を与える可能性があります。例えば、コマンドを実行してリソースを作成すると、最終的に他のコマンドに表示されます。つまり、その作成したリソースを変更または記述するコマンドを実行すると、その ID がシステム全体に伝播されず、リソースが存在しないことを示すエラーが表示されます。

結果整合性を管理するには、以下を実行します。
+ コマンドを実行して変更する前に、リソースの状態を確認します。エクスポネンシャルバックオフアルゴリズムを使用して適切な `Describe` コマンドを実行し、前のコマンドがシステム内を伝播するのに十分な時間を確保できるようにします。これを行うには、数秒の待機時間から始めて`Describe`コマンドを繰り返し実行し、数分間の待機時間まで徐々に増やします。
+ `Describe` コマンドが正確なレスポンスを返した場合でも、後続のコマンド間の待機時間を追加します。数秒の待機時間から始まる指数バックオフアルゴリズムを適用し、数分間まで徐々に増やします。

**結果整合性エラーの例**  
以下は、結果整合性の結果として発生する可能性のあるエラーコードの例です。
+ `InvalidInstanceID.NotFound`

  `RunInstances` コマンドを正常に実行し、`RunInstances` のレスポンスで指定されたインスタンス ID を使用して別のコマンドをすぐに実行すると、`InvalidInstanceID.NotFound` エラーが返される可能性があります。これは、インスタンスが存在しないことを意味するものではありません。

  影響を受ける可能性のある特定のコマンドは次のとおりです。
  + `DescribeInstances`: インスタンスの実際の状態を確認するには、エクスポネンシャルバックオフアルゴリズムを使用してこのコマンドを実行します。
  + `TerminateInstances`: インスタンスの状態を確認するには、まずエクスポネンシャルバックオフアルゴリズムを使用して `DescribeInstances` コマンドを実行します。
**重要**  
`TerminateInstances` の実行後に `InvalidInstanceID.NotFound` エラーが発生しても、インスタンスが終了していたり、終了するわけではありません。インスタンスはまだ実行中である可能性があります。そのため、`DescribeInstances` を使用してインスタンスの状態を最初に確認することが重要です。
+ `InvalidGroup.NotFound`

  `CreateSecurityGroup` コマンドを正常に実行し、`CreateSecurityGroup` のレスポンスで提供されたセキュリティグループ ID を使用して別のコマンドをすぐに実行すると、`InvalidGroup.NotFound` エラーが返される場合があります。セキュリティグループの状態を確認するには、エクスポネンシャルバックオフアルゴリズムを使用して `DescribeSecurityGroups` コマンドを実行します。
+ `InstanceLimitExceeded`

  指定されたインスタンスタイプに対して現在のインスタンスの上限を超えるインスタンスをリクエストしました。インスタンスを起動してすぐに終了する場合に、この上限に予期せず到達する可能性があります。これは、インスタンスが終了してからしばらくの間、終了したインスタンスがインスタンスの上限に対してカウントされるためです。

# Ensuring idempotency in Amazon EC2 API requests
<a name="ec2-api-idempotency"></a>

変異する API リクエストを行うと、通常、リクエストはオペレーションの非同期ワークフローが完了する前に結果を返します。リクエストが既に結果を返している場合でも、操作が完了する前にタイムアウトしたり、その他のサーバーの問題が発生したりすることもあります。これにより、リクエストが成功したかどうかを判断するのが難しくなり、操作を正常に完了するために複数回の再試行が行われることがあります。ただし、元のリクエストとその後の再試行が成功すると、操作は複数回完了します。つまり、意図したよりも多くのリソースが作成される可能性があります。

*冪等性*とは、API リクエストが 1 回だけ完了することを保証するものです。冪等性リクエストでは、元のリクエストが正常に完了した場合、その後の再試行は追加のアクションを実行せずに正しく完了します。ただし、結果には、現在の作成ステータスなどの更新された情報が含まれる場合があります。

**Topics**
+ [Amazon EC2 のべき等性](#client-tokens)
+ [RunInstances のべき等性](#run-instances-idempotency)
+ [例](#Run_Instance_Idempotency_CLI)
+ [べき等リクエストの再試行の推奨事項](#recommended-actions)

## Amazon EC2 のべき等性
<a name="client-tokens"></a>

以下の API アクションはデフォルトでべき等であり、追加の設定は必要ありません。対応する AWS CLI コマンドも、デフォルトでべき等性をサポートしています。

**デフォルトでべき等**
+ AssociateAddress
+ CreateVpnConnection
+ DisassociateAddress
+ ReplaceNetworkAclAssociation
+ TerminateInstances

次の API アクションは、オプションで*クライアントトークン*を使用したべき等性をサポートしています。対応する AWS CLI コマンドも、クライアントトークンを使用したべき等性をサポートしています。クライアントトークンは、最大 64 バイトの ASCII 文字で、大文字と小文字を区別する一意の文字列です。これらのアクションのいずれかを使用してべき等 API リクエストを行うには、リクエストでクライアントトークンを指定します。同じクライアントトークンを他の API リクエストに再利用しないでください。同じクライアントトークンと同じパラメータを使用して正常に完了したリクエストを再試行すると、それ以上のアクションを実行せずに再試行が成功します。同じクライアントトークンを使用して成功したリクエストを再試行しても、リージョンまたはアベイラビリティーゾーン以外の 1 つ以上のパラメータが異なる場合、再試行は `IdempotentParameterMismatch` エラーで失敗します。

**クライアントトークンを使用したべき等性**
+ AllocateHosts
+ AllocateIpamPoolCidr
+ AssociateClientVpnTargetNetwork
+ AssociateIpamResourceDiscovery
+ AttachVerifiedAccessTrustProvider
+ AuthorizeClientVpnIngress
+ CopyFpgaImage
+ CopyImage
+ CreateCapacityReservation
+ CreateCapacityReservationFleet
+ CreateClientVpnEndpoint
+ CreateClientVpnRoute
+ CreateEgressOnlyInternetGateway
+ CreateFleet
+ CreateFlowLogs
+ CreateFpgaImage
+ CreateInstanceConnectEndpoint
+ CreateIpam
+ CreateIpamPool
+ CreateIpamResourceDiscovery
+ CreateIpamScope
+ CreateLaunchTemplate
+ CreateLaunchTemplateVersion
+ CreateManagedPrefixList
+ CreateNatGateway
+ CreateNetworkAcl
+ CreateNetworkInsightsAccessScope
+ CreateNetworkInsightsPath
+ CreateNetworkInterface
+ CreateReplaceRootVolumeTask
+ CreateReservedInstancesListing
+ CreateRouteTable
+ CreateTrafficMirrorFilter
+ CreateTrafficMirrorFilterRule
+ CreateTrafficMirrorSession
+ CreateTrafficMirrorTarget
+ CreateVerifiedAccessEndpoint
+ CreateVerifiedAccessGroup
+ CreateVerifiedAccessInstance
+ CreateVerifiedAccessTrustProvider
+ CreateVolume
+ CreateVpcEndpoint
+ CreateVpcEndpointConnectionNotification
+ CreateVpcEndpointServiceConfiguration
+ DeleteVerifiedAccessEndpoint
+ DeleteVerifiedAccessGroup
+ DeleteVerifiedAccessInstance
+ DeleteVerifiedAccessTrustProvider
+ DetachVerifiedAccessTrustProvider
+ ExportImage
+ ImportImage
+ ImportSnapshot
+ ModifyInstanceCreditSpecification
+ ModifyLaunchTemplate
+ ModifyReservedInstances
+ ModifyVerifiedAccessEndpoint
+ ModifyVerifiedAccessEndpointPolicy
+ ModifyVerifiedAccessGroup
+ ModifyVerifiedAccessGroupPolicy
+ ModifyVerifiedAccessInstance
+ ModifyVerifiedAccessInstanceLoggingConfiguration
+ ModifyVerifiedAccessTrustProvider
+ ProvisionIpamPoolCidr
+ PurchaseHostReservation
+ RequestSpotFleet
+ RequestSpotInstances
+ RunInstances
+ StartNetworkInsightsAccessScopeAnalysis
+ StartNetworkInsightsAnalysis

**べき等性のタイプ**
+ リージョン – リクエストは各リージョンでべき等です。ただし、同じクライアントトークンを含む同じリクエストを別のリージョンで使用できます。
+ ゾーン – リクエストは、リージョン内の各アベイラビリティーゾーンでべき等です。たとえば、同じリージョンの **AllocateHosts** への 2 回の呼び出しで同じクライアントトークンを指定した場合、**AvailabilityZone** パラメータに異なる値を指定すると、呼び出しは成功します。

## RunInstances のべき等性
<a name="run-instances-idempotency"></a>

[RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API アクションは、リージョンとゾーンの両方のべき等性を使用します。

使用されるべき等性のタイプは、RunInstances API リクエストでアベイラビリティーゾーンを指定する方法によって異なります。リクエストは、次の場合に**ゾーンのべき等性**を使用します。
+ **プレイスメント**データ型で **AvailabilityZone** パラメータを使用してアベイラビリティーゾーンを明示的に指定する場合
+ **SubnetId** パラメータを使用して暗黙的にアベイラビリティーゾーンを指定する場合

アベイラビリティーゾーンを明示的または暗黙的に指定しない場合、リクエストでは**リージョンのべき等性**を使用します。

### ゾーンのべき等性
<a name="zonal-idempotency"></a>

ゾーンのべき等性により、RunInstances API リクエストがリージョン内の各アベイラビリティーゾーンでべき等であることが保証されます。これにより、同じクライアントトークンを使用するリクエストは、リージョン内の各アベイラビリティーゾーン内で 1 回だけ完了できます。ただし、同じクライアントトークンを使用して、リージョン内の他のアベイラビリティーゾーンでインスタンスを起動できます。

たとえば、べき等リクエストを送信して `us-east-1a` アベイラビリティーゾーンでインスタンスを起動し、`us-east-1b` アベイラビリティーゾーンのリクエストで同じクライアントトークンを使用する場合、それらの各アベイラビリティーゾーンでインスタンスを起動します。1 つ以上のパラメータが異なる場合、それらのアベイラビリティーゾーンで同じクライアントトークンを使用した後続の再試行は、それ以上のアクションを実行せずに正常に返されるか、`IdempotentParameterMismatch` エラーで失敗します。

### リージョンのべき等性
<a name="regional-idempotency"></a>

リージョンのべき等性により、RunInstances API リクエストがリージョンでべき等であることが保証されます。これにより、同じクライアントトークンを使用するリクエストは、リージョン内で 1 回のみ完了できます。ただし、同じクライアントトークンを使用するまったく同じリクエストを使用して、別のリージョンでインスタンスを起動できます。

たとえば、`us-east-1` リージョンでインスタンスを起動するべき等リクエストを送信し、次に `eu-west-1` リージョンのリクエストで同じクライアントトークンを使用する場合、それらの各リージョンでインスタンスを起動します。1 つ以上のパラメータが異なる場合、それらのリージョンで同じクライアントトークンを使用した後続の再試行は、それ以上のアクションを実行せずに正常に返されるか、`IdempotentParameterMismatch` エラーで失敗します。

**ヒント**  
リクエストされたリージョンのアベイラビリティーゾーンのいずれかが利用できない場合、リージョンのべき等性を使用する RunInstances リクエストは失敗する可能性があります。AWS インフラストラクチャが提供するアベイラビリティーゾーンの機能を活用するには、インスタンスの起動時にゾーンのべき等性を使用することをお勧めします。ゾーンのべき等性を使用し、利用可能なアベイラビリティーゾーンをターゲットとする RunInstances リクエストは、リクエストされたリージョン内の別のアベイラビリティーゾーンが利用できない場合でも成功します。

## 例
<a name="Run_Instance_Idempotency_CLI"></a>

### AWS CLI コマンドの例
<a name="cli-example"></a>

AWS CLI コマンドをべき等にするには、`--client-token` オプションを追加します。

**例 1: べき等性**  
次の [allocate-hosts](https://docs.aws.amazon.com/cli/latest/reference/ec2/allocate-hosts.html) コマンドは、クライアントトークンを含むため、べき等性を使用します。

```
aws ec2 allocate-hosts  --instance-type m5.large  --availability-zone eu-west-1a  --auto-placement on  --quantity 1 --client-token 550e8400-e29b-41d4-a716-446655440000
```

**例 2: run-instances リージョンのべき等性**  
次の [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) コマンドは、クライアントトークンを含むため、リージョンのべき等性を使用しますが、明示的にも暗黙的にもアベイラビリティーゾーンを指定しません。

```
aws ec2 run-instances --image-id ami-b232d0db --count 1 --key-name my-key-pair --client-token 550e8400-e29b-41d4-a716-446655440000
```

**例 3: run-instances ゾーンのべき等性**  
次の [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) コマンドは、クライアントトークンと明示的に指定されたアベイラビリティーゾーンを含むため、ゾーンのべき等性を使用します。

```
aws ec2 run-instances  --placement "AvailabilityZone=us-east-1a" --image-id ami-b232d0db --count 1 --key-name my-key-pair --client-token 550e8400-e29b-41d4-a716-446655440000
```

### API リクエストの例
<a name="api-example"></a>

API リクエストをべき等にするには、`ClientToken` パラメータを追加します。

**例 1: べき等性**  
次の [AllocateHosts](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AllocateHosts.html) API リクエストは、クライアントトークンを含むためべき等性を使用します。

```
https://ec2.amazonaws.com/?Action=AllocateHosts
&AvailabilityZone=us-east-1b
&InstanceType=m5.large
&Quantity=1
&AutoPlacement=off
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

**例 2: RunInstances リージョンのべき等性**  
次の [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API リクエストは、クライアントトークンを含むため、リージョンのべき等性を使用しますが、明示的にも暗黙的にもアベイラビリティーゾーンを指定しません。

```
https://ec2.amazonaws.com/?Action=RunInstances
&ImageId=ami-3ac33653
&MaxCount=1
&MinCount=1
&KeyName=my-key-pair
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

**例 3: RunInstances ゾーンのべき等性**  
次の [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API リクエストでは、クライアントトークンと明示的に指定されたアベイラビリティーゾーンが含まれているため、ゾーンのべき等性を使用します。

```
https://ec2.amazonaws.com/?Action=RunInstances
&Placement.AvailabilityZone=us-east-1d
&ImageId=ami-3ac33653
&MaxCount=1
&MinCount=1
&KeyName=my-key-pair
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

## べき等リクエストの再試行の推奨事項
<a name="recommended-actions"></a>

次の表は、べき等 API リクエストに対して返される一般的な応答と、再試行の推奨事項を示しています。


| 応答 | 推奨事項 | コメント | 
| --- | --- | --- | 
|  200 (OK)  |  再試行しないでください  |  元のリクエストは正しく完了しています。それ以降に再試行しても正常に戻ります。  | 
|  400 シリーズ応答コード ([クライアントエラー](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html#CommonErrors))  |  再試行しないでください  |  次のうち、リクエストに問題があります。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/ec2/latest/devguide/ec2-api-idempotency.html) リクエストに状態の変更処理中のリソースが含まれている場合、リクエストを再試行すると成功する可能性があります。  | 
|  500 シリーズ応答コード ([サーバーエラー](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html#api-error-codes-table-server))  |  再試行  |  このエラーは AWS サーバー側の問題によって発生し、通常は一時的なものです。適切なバックオフ戦略でリクエストを繰り返してください。  | 

# Amazon EC2 API リクエストのスロットリング
<a name="ec2-api-throttling"></a>

Amazon EC2 は、リージョンごとに各 AWS アカウントの EC2 API リクエストを調整します。これは、サービスのパフォーマンスを向上し、Amazon EC2 のすべてのユーザーに平等にご利用いただくために行われるものです。スロットリングにより、Amazon EC2 API へのリクエストが API リクエストの最大許容上限を超えないことが保証されます。API リクエストは、送信元が以下であるかどうかにかかわらず、リクエストの上限の対象となります。
+ サードパーティーのアプリケーション
+ コマンドラインツール
+ Amazon EC2 コンソール

API スロットリング上限を超えると、`RequestLimitExceeded` エラーコードが返されます。

**Topics**
+ [スロットリングの適用方法](#throttling-how)
+ [リクエストトークンの上限](#throttling-limits-rate-based)
+ [リソーストークンの上限](#throttling-limits-cost-based)
+ [API スロットリングをモニタリングする](#throttling-monitor)
+ [再試行とエクスポネンシャルバックオフ](#api-backoff)
+ [制限の引き上げのリクエスト](#throttling-increase)

## スロットリングの適用方法
<a name="throttling-how"></a>

Amazon EC2 では[トークンバケットアルゴリズム](https://en.wikipedia.org/wiki/Token_bucket)を使用して、API スロットリングを実装します。このアルゴリズムでは、アカウントには、特定の数の*トークン*を保持する*バケット*があります。バケット内のトークンの数は、特定の秒におけるスロットリング上限を表します。

Amazon EC2 では 2 種類の API スロットリングを実装します。

**Topics**
+ [リクエストレート制限](#throttling-rate-based)
+ [リソースレート制限](#throttling-cost-based)

### リクエストレート制限
<a name="throttling-rate-based"></a>

リクエストレート制限により各 API が個別に評価され、ユーザーは、API ごとに行うリクエストの数に応じてスロットリングされます。リクエストを行うことに、API のバケットからトークンが 1 つ削除されます。例えば、`DescribeHosts` (*非変化* API アクション) のトークンバケットサイズは 100 トークンです。1 秒あたり最大 100 個の `DescribeHosts` リクエストを行うことができます。1 秒あたりのリクエストが 100 個を超えると、その API でスロットリングされ、その秒内の残りのリクエストは失敗しますが、他の API のリクエストは影響を受けません。

バケットは設定されたレートで自動的に補充されます。バケットが最大容量に達していない場合、最大容量に達するまで、設定した数のトークンが毎秒追加されます。リフィルトークンが到着したときにバケットが満杯である場合、リフィルトークンは破棄されます。バケットは最大数を超えてトークンを保持することはできません。例えば、`DescribeHosts` (*非変化* API アクション) のバケットサイズが 100 トークンで、リフィルレートが 1 秒あたり 20 トークンであるとします。1 秒間に 100 個の `DescribeHosts` リクエストを行うと、バケットはゼロ (0) トークンまで減らされます。バケットは、最大容量の 100 トークンに達するまで、毎秒最大 20 トークンで補充されます。つまり、空のバケットは、その間にリクエストが行われなかった場合、5 秒後に最大容量に達します。

API リクエストを行う前に、バケットが完全にいっぱいになるまで待つ必要はありません。リフィルトークンはバケットに追加されると使用できます。リフィルトークンをすぐに使用しても、バケットが最大容量に達することはありません。例えば、`DescribeHosts` (*非変化* API アクション) のバケットサイズが 100 トークンで、リフィルレートが 1 秒あたり 20 トークンであるとします。1 秒あたり 100 個の API リクエストを行ってバケットを使い果たした場合、バケットに追加されるリフィルトークンを使用して、1 秒あたり 20 個の API リクエストを引き続き行うことができます。バケットは、1 秒あたり 20 個未満の API リクエストを行う場合のみ、最大容量に補充できます。

詳細については、「[リクエストトークンバケットのサイズとリフィルレート](#throttling-limits-rate-based)」を参照してください。

### リソースレート制限
<a name="throttling-cost-based"></a>

次の表で説明されるように、`RunInstances` や `TerminateInstances` などの一部の API アクションでは、リクエストレート制限に加えてリソースレート制限を使用します。これらの API アクションには、リクエストの影響を受けるリソースの数に基づいて消費される個別のリソーストークンバケットがあります。リクエストトークンバケットと同様に、リソーストークンバケットにはバーストできるバケットの最大数と、必要な期間にわたって安定したリクエストレートを維持できるリフィルレートがあります。バケットが次の API リクエストをサポートするために補充されていない場合など、API の特定のバケットの上限を超えた場合、API スロットル制限の合計に達していなくても、API のアクションは制限されます。

例えば、`RunInstances` のリソーストークンバケットサイズは 1000 トークンで、リフィルレートは 1 秒あたり 2 トークンです。したがって、1000 インスタンスの 1 個のリクエストや 250 インスタンスの 4 個のリクエストなど、任意の数の API リクエストを使用して、1000 インスタンスをすぐに起動できます。リソーストークンバケットが空になったら、2 つのインスタンスに対して 1 つのリクエストを使用するか、1 つのインスタンスに対して 2 つのリクエストを使用して、毎秒最大 2 つのインスタンスを起動できます。

詳細については、「[リソーストークンバケットのサイズとリフィルレート](#throttling-limits-cost-based)」を参照してください。

## リクエストトークンバケットのサイズとリフィルレート
<a name="throttling-limits-rate-based"></a>

リクエストレート制限の目的で、API アクションは次のカテゴリに分類されます。
+ **非変化アクション** — リソースに関するデータを取得する API アクション。このカテゴリには通常、`DescribeRouteTables`、`SearchTransitGatewayRoutes`、`GetIpamPoolCidrs` などの、すべての `Describe*`、`List*`、`Search*`、`Get*` API アクションが含まれます。これらの API アクションは通常、API スロットリング上限が最も高くなります。
+ **フィルタリングされていない非変化アクションとページ分割されていない非変化アクション** — 非変化 API アクションの特定のサブセット。[[ページ分割]](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-pagination.html) または [[フィルター]](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/Using_Filtering.html#Filtering_Resources_CLI) を指定せずにリクエストされた場合に、より小さなトークンバケットのトークンを使用します。トークンが標準 (より大きな) トークンバケットから引かれるように、ページ分割とフィルタリングを使用することをお勧めします。
+ **変化アクション** – リソースを作成、変更、または削除する API アクション。このカテゴリには通常、`AllocateHosts`、`ModifyHosts`、`CreateCapacityReservation` などの *非変化アクション*として分類されていないすべての API アクションが含まれます。これらのアクションは、非変化 API アクションよりもスロットリング上限が低くなります。
+ **リソース集約型アクション** — 完了するのに最も時間がかかり、最も多くのリソースを消費する変化 API アクション。これらのアクションのスロットリング上限は、*変化アクション*よりもさらに低くなります。これらは、他の*変化アクション*とは別にスロットリングされます。
+ **コンソールの非変化アクション** — Amazon EC2 コンソールからリクエストされる非変化 API アクション。これらの API アクションは、他の非変化 API アクションとは別にスロットリングされます。
+ **未分類アクション** — これらは、定義上、他のカテゴリのいずれかに該当していても、独自のトークンバケットサイズとリフィルレートを受け取る API アクションです。


| API アクションカテゴリ | アクション | バケットの最大容量 | バケットリフィルレート | 
| --- | --- | --- | --- | 
| 非変化アクション |  別のカテゴリに含まれていない `Describe*`、`List*`、`Search*`、`Get*` API アクション。  | 100 | 20 | 
| フィルタリングされていない非変化アクションとページ分割されていない非変化アクション |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/ec2/latest/devguide/ec2-api-throttling.html)  | 50 | 10 | 
| 変化アクション | *リソース集約型アクション*でも*未分類アクション*でもないすべての変化 API アクション。 | 50 | 5 | 
| リソース集約型アクション |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/ec2/latest/devguide/ec2-api-throttling.html)  | 50 | 5 | 
| コンソール非変化アクション |  Amazon EC2 コンソールによって呼び出されますが、別のカテゴリには含まれない `Describe*`、`List*`、`Search*`、`Get*` API アクション。  | 100 | 10 | <a name="uncategorized"></a>


| 未分類アクション | バケットの最大容量 | バケットリフィルレート | 
| --- | --- | --- | 
| AcceptVpcEndpointConnections | 10 | 1 | 
| AdvertiseByoipCidr | 1 | 0.1 | 
| AssignIpv6Addresses | 100 | 5 | 
| AssignPrivateIpAddresses | 100 | 5 | 
| AssignPrivateNatGatewayAddress | 10 | 1 | 
| AssociateCapacityReservationBillingOwner | 1 | 0.5 | 
| AssociateEnclaveCertificateIamRole | 10 | 1 | 
| AssociateIamInstanceProfile | 100 | 5 | 
| AssociateNatGatewayAddress | 10 | 1 | 
| AttachVerifiedAccessTrustProvider | 10 | 2 | 
| AuthorizeClientVpnIngress | 5 | 2 | 
| CancelDeclarativePoliciesReport | 1 | 1 | 
| CopyImage | 100 | 1 | 
| CreateClientVpnRoute | 5 | 2 | 
| CreateCoipCidr | 5 | 1 | 
| CreateCoipPool | 5 | 1 | 
| CreateDefaultSubnet | 1 | 1 | 
| CreateDefaultVpc | 1 | 1 | 
| CreateLaunchTemplateVersion | 100 | 5 | 
| CreateNatGateway | 10 | 1 | 
| CreateNetworkInterface | 100 | 5 | 
| CreateRestoreImageTask | 50 | 0.1 | 
| CreateSnapshot | 100 | 5 | 
| CreateSnapshots | 100 | 5 | 
| CreateSpotDatafeedSubscription | 50 | 3 | 
| CreateStoreImageTask | 50 | 0.1 | 
| CreateSubnetCidrReservation | 5 | 1 | 
| CreateTags | 100 | 10 | 
| CreateVerifiedAccessEndpoint | 20 | 4 | 
| CreateVerifiedAccessGroup | 10 | 2 | 
| CreateVerifiedAccessInstance | 10 | 2 | 
| CreateVerifiedAccessTrustProvider | 10 | 2 | 
| CreateVolume | 100 | 5 | 
| CreateVpcEndpoint | 4 | 0.3 | 
| CreateVpcEndpointServiceConfiguration | 10 | 1 | 
| DeleteClientVpnRoute | 5 | 2 | 
| DeleteCoipCidr | 5 | 1 | 
| DeleteCoipPool | 5 | 1 | 
| DeleteCoipPoolPermission | 5 | 1 | 
| DeleteNatGateway | 10 | 1 | 
| DeleteNetworkInterface | 100 | 5 | 
| DeleteSnapshot | 100 | 5 | 
| DeleteSpotDatafeedSubscription | 50 | 3 | 
| DeleteSubnetCidrReservation | 5 | 1 | 
| DeleteQueuedReservedInstances | 5 | 5 | 
| DeleteTags | 100 | 10 | 
| DeleteVerifiedAccessEndpoint | 20 | 4 | 
| DeleteVerifiedAccessGroup | 10 | 2 | 
| DeleteVerifiedAccessInstance | 10 | 2 | 
| DeleteVerifiedAccessTrustProvider | 10 | 2 | 
| DeleteVolume | 100 | 5 | 
| DeleteVpcEndpoints | 4 | 0.3 | 
| DeleteVpcEndpointServiceConfigurations | 10 | 1 | 
| DeprovisionByoipCidr | 1 | 0.1 | 
| DeregisterImage | 100 | 5 | 
| DescribeAggregateIdFormat | 10 | 10 | 
| DescribeByoipCidrs | 1 | 0.5 | 
| DescribeCapacityBlockExtensionOfferings | 10 | 0.15 | 
| DescribeCapacityBlockOfferings | 10 | 0.15 | 
| DescribeDeclarativePoliciesReports | 5 | 5 | 
| DescribeHostReservations | 5 | 2 | 
| DescribeHostReservationOfferings | 5 | 2 | 
| DescribeIdentityIdFormat | 10 | 10 | 
| DescribeIdFormat | 10 | 10 | 
| DescribeInstanceTopology | 1 | 1 | 
| DescribeMovingAddresses | 1 | 1 | 
| DescribePrincipalIdFormat | 10 | 10 | 
| DescribeReservedInstancesOfferings | 10 | 10 | 
| DescribeSecurityGroupReferences | 20 | 5 | 
| DescribeSpotDatafeedSubscription | 100 | 13 | 
| DescribeSpotFleetInstances | 100 | 5 | 
| DescribeSpotFleetRequestHistory | 100 | 5 | 
| DescribeSpotFleetRequests | 50 | 3 | 
| DescribeStaleSecurityGroups | 20 | 5 | 
| DescribeStoreImageTasks | 50 | 0.5 | 
| DescribeVerifiedAccessInstanceLoggingConfigurations | 10 | 2 | 
| DetachVerifiedAccessTrustProvider | 10 | 2 | 
| DisableFastLaunch | 5 | 2 | 
| DisableImageBlockPublicAccess | 1 | 0.1 | 
| DisableSnapshotBlockPublicAccess | 1 | 0.1 | 
| DisassociateCapacityReservationBillingOwner | 1 | 0.5 | 
| DisassociateEnclaveCertificateIamRole | 10 | 1 | 
| DisassociateIamInstanceProfile | 100 | 5 | 
| DisassociateNatGatewayAddress | 10 | 1 | 
| EnableFastLaunch | 5 | 2 | 
| EnableImageBlockPublicAccess | 1 | 0.1 | 
| EnableSnapshotBlockPublicAccess | 1 | 0.1 | 
| GetAssociatedEnclaveCertificateIamRoles | 10 | 1 | 
| GetDeclarativePoliciesReportSummary | 5 | 5 | 
| GetHostReservationPurchasePreview | 5 | 2 | 
| ModifyImageAttribute | 100 | 5 | 
| ModifyInstanceMetadataDefaults | 2 | 2 | 
| ModifyInstanceMetadataOptions | 100 | 5 | 
| ModifyLaunchTemplate | 100 | 5 | 
| ModifyNetworkInterfaceAttribute | 100 | 5 | 
| ModifySnapshotAttribute | 100 | 5 | 
| ModifyVerifiedAccessEndpoint | 20 | 4 | 
| ModifyVerifiedAccessEndpointPolicy | 20 | 4 | 
| ModifyVerifiedAccessGroup | 10 | 2 | 
| ModifyVerifiedAccessGroupPolicy | 20 | 4 | 
| ModifyVerifiedAccessInstance | 10 | 2 | 
| ModifyVerifiedAccessInstanceLoggingConfiguration | 10 | 2 | 
| ModifyVerifiedAccessTrustProvider | 10 | 2 | 
| ModifyVpcEndpoint | 4 | 0.3 | 
| ModifyVpcEndpointServiceConfiguration | 10 | 1 | 
| MoveAddressToVpc | 1 | 1 | 
| ProvisionByoipCidr | 1 | 0.1 | 
| PurchaseCapacityBlock | 10 | 0.15 | 
| PurchaseCapacityBlockExtension | 10 | 0.15 | 
| PurchaseHostReservation | 5 | 2 | 
| PurchaseReservedInstancesOffering | 5 | 5 | 
| RejectVpcEndpointConnections | 10 | 1 | 
| RestoreAddressToClassic | 1 | 1 | 
| RevokeClientVpnIngress | 5 | 2 | 
| RunInstances | 5 | 2 | 
| StartDeclarativePoliciesReport | 1 | 1 | 
| StartInstances | 5 | 2 | 
| TerminateInstances | 100 | 5 | 
| UnassignPrivateIpAddresses | 100 | 5 | 
| UnassignPrivateNatGatewayAddress | 10 | 1 | 
| WithdrawByoipCidr | 1 | 0.1 | 

## リソーストークンバケットのサイズとリフィルレート
<a name="throttling-limits-cost-based"></a>

次の表に、リソースレート制限を使用する API アクションのリソーストークンバケットのサイズとリフィルレートを示します。


| API アクション | バケットの最大容量 | バケットリフィルレート | 
| --- | --- | --- | 
| RunInstances | 1,000 | 2 | 
| TerminateInstances | 1,000 | 20 | 
| StartInstances | 1,000 | 2 | 
| StopInstances | 1,000 | 20 | 

## API スロットリングをモニタリングする
<a name="throttling-monitor"></a>

Amazon CloudWatch を使用して Amazon EC2 API リクエストをモニタリングし、API スロットリングに関するメトリクスを収集および追跡できます。API スロットリング上限に近づいたときに警告するアラームを作成することもできます。詳細については、「[Amazon CloudWatch を使用して Amazon EC2 API リクエストをモニタリングするCloudWatch を使用して API リクエストをモニタリングする](monitor.md)」を参照してください。

## 再試行とエクスポネンシャルバックオフ
<a name="api-backoff"></a>

アプリケーションで、API リクエストの再試行が必要な場合があります。例えば、次のようになります。
+ リソースのステータスの更新を確認するには
+ 多数のリソース (すべてのボリュームなど) を列挙するには
+ サーバーエラー (5xx) またはスロットリングエラーでリクエストが失敗した後に再試行するには

ただし、クライアントエラー (4xx) は、リクエスト再試行する前にリクエストを修正して問題を解決する必要があります。

**リソースの状態変更**  
状態変更を確認するためのポーリングを開始する前に、リクエストの予想完了時間を指定します。例えば、インスタンスがアクティブかどうかを確認するまで数分待ちます。ポーリングを開始する時に、連続するリクエストの間に適切なスリープ間隔を使用して API リクエストレートを下げます。最良の結果を得るには、漸増または可変スリープ間隔を使用します。

または、Amazon EventBridge を使用して、一部のリソースのステータスを通知することもできます。例えば、**EC2 インスタンスの状態変更通知**イベントを使用して、インスタンスの状態変更を通知できます。詳細については、「[EventBridge を使用して Amazon EC2 を自動化する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/automating_with_eventbridge.html)」を参照してください。

**再試行**  
API リクエストをポーリングまたは再試行する必要がある場合は、エクスポネンシャルバックオフ アルゴリズムを使用して API リクエスト間のスリープ間隔を計算することをお勧めします。エクスポネンシャルバックオフの背後にある考え方は、連続したエラー応答の再試行間の待機時間を徐々に長く使用することです。最大遅延間隔と最大再試行回数を実装する必要があります。ジッター (ランダム化された遅延) を使用して、連続する衝突を防ぐこともできます。詳細については、「[タイムアウト、リトライ、ジッターによるバックオフ](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)」を参照してください。

各 AWS SDK は自動再試行ロジックを実装します。詳細については、「*AWS SDK とツールのリファレンスガイド*」の「[再試行動作](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)」を参照してください。

## 制限の引き上げのリクエスト
<a name="throttling-increase"></a>

 AWS アカウントの API スロットリング上限の引き上げをリクエストできます。

**レコメンデーション**
+ 1 つのリクエストで既存の上限の最大 3 倍をリクエストします。
+ バケットの最大容量を増やす前に、バケットリフィルレートの増加を優先します。
+ リクエストされたバケットリフィルレートがバケットの最大容量を超える場合は、バケットの最大容量を同時に増やします。
+ 増加が必要なすべての API アクションを指定します。上限は、API アクションのカテゴリではなく、個々の API アクションに適用されます。
+ `RunInstances`、`StartInstances`、`StopInstances`、`TerminateInstances` の API アクションにはリクエストレートとリソースレートの両方の上限があります。引き上げる上限を必ず指定してください。

**この機能へのアクセスをリクエストするには**

1. [AWS サポート センター](https://console.aws.amazon.com/support/home#/)を開きます。

1. **[ケースを作成]** を選択します。

1. **[Account and billing]** (アカウントおよび請求) を選択します。

1. **[サービス]** で **[一般情報と開始方法] **を選択します。

1. **カテゴリ** で、「**Using AWS & Services**」を選択します。

1. **[次のステップ: 追加情報]** を選択します。

1. [**Subject (件名)**] に **Request an increase in my Amazon EC2 API throttling limits** と入力します。

1. **[説明]** には、次のテンプレートをコピーし、必要な情報を入力します。

   ```
   Please increase the API throttling limits for my account. 
   Related page: https://docs.aws.amazon.com/ec2/latest/devguide/ec2-api-throttling.html
   Description: Brief notes about your use case. If available, include the IDs
       of a few Amazon EC2 requests that were throttled.
   Time window: One-hour window when peak throttling or usage occurred.
   region_1 request rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_1 resource rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_2 request rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_2 resource rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   ```

1. **[次のステップ: 今すぐ解決するか、お問い合わせください]** を選択します。

1. **[お問い合わせ]** タブをクリックし、連絡の際に希望する言語と連絡方法を選択します。

1. [**Submit**] を選択します。

# Amazon EC2 API でのページ分割
<a name="ec2-api-pagination"></a>

`DescribeInstances` など、多数の結果を返す可能性のある記述アクションを呼び出す場合は、ページ分割を使用することをお勧めします。ページ分割を使用すると、記述呼び出しによって返される項目の数と、呼び出しが戻るのにかかる時間が制限されます。多数のリソースがある場合、ページ分割されていない呼び出しはスロットリングされ、タイムアウトする可能性があります。したがって、ページ分割された呼び出しは一貫して成功するため、ページ分割されていない呼び出しよりもページ分割された呼び出しの方が全体的なレイテンシーが優れています。

詳細については、「*Amazon EC2 API リファレンス*」の「[Pagination](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Query-Requests.html#api-pagination)」(ページネーション) を参照してください。

## ベストプラクティス
<a name="pagination-best-practices"></a>

可能な場合は、記述呼び出しでリソース ID のリストを指定します。これは、多数のリソースを記述する最も速い方法です。1 回の呼び出しで 1,000 を超える ID を指定しないでください。以下に例を示します。

```
private List<Reservation> describeMyInstances(List<String> ids){
    if (ids == null || ids.isEmpty()) {
        return ImmutableList.of();
    }
        
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```

記述呼び出しでリソース ID を指定できない場合は、ページ分割を使用することを強くお勧めします。以下に例を示します。

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters)
            .withMaxResults(1000);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```

ページ分割された呼び出しを再試行する必要がある場合は、[ジッターでエクスポネンシャルバックオフ](ec2-api-throttling.md#api-backoff)を使用します。

## 一般的な問題
<a name="pagination-common-issues"></a>

以下は、誤ってページ分割されていない呼び出しを行うコードの例です。

**Example 問題の例: リソース ID の空のリストを渡す**  
次のコードは ID のリストを使用します。ただし、リストが空の場合、結果はページ分割されていない呼び出しになります。  

```
private List<Reservation> describeMyInstances(List<String> ids){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```
この問題を修正するには、記述呼び出しを行う前にリストが空でないことを確認してください。  

```
private List<Reservation> describeMyInstances(List<String> ids){
    if (ids == null || ids.isEmpty()) {
        return ImmutableList.of();
        // OR
        return Lists.newArrayList();
        // OR
        return new ArrayList<>();
    }
        
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```

**Example 問題の例: MaxResults を設定しない**  
次のコードは `nextToken` をチェックして使用しますが、`MaxResults` を設定しません。  

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```
この問題を修正するには、次のように `withMaxResults` を追加します。  

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters)
            .withMaxResults(1000);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```