

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

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

当您发出变更 API 请求时，该请求通常会在操作的异步工作流完成之前返回结果。即使请求已经返回结果，操作在完成之前也可能会超时或遇到其他服务器问题。这样就很难确定请求是否成功，并且会导致进行多次重试以确保操作成功完成。但是，如果原始请求和后续重试成功，则会多次完成操作。这意味着您可能会创建超过预期数量的资源。

*幂等性*确保 API 请求完成不超过一次。对于幂等性请求，如果原始请求成功完成，则后续重试也会成功完成，而不会执行任何后续操作。不过，结果中可能包含更新后的信息，例如当前的创建状态。

**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 请求。如果您使用相同的客户端令牌并保持所有参数一致来重试一个已成功完成的请求，该重试会直接成功，而不会执行任何额外操作。如果您在重试成功的请求时使用了相同的客户端令牌，但一个或多个参数发生变化（区域或可用区除外），重试将失败，并返回 `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** 调用中使用相同的客户端令牌，只要它们的 **AvailabilityZone** 参数值不同，这两个调用都会成功。

## RunInstances 的幂等性
<a name="run-instances-idempotency"></a>

[RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 操作同时采用区域级和可用区级幂等性。

具体采用哪种幂等性，取决于您在 RunInstances API 请求中如何指定可用区。在以下情况中，请求会使用**可用区级幂等性**：
+ 您在 **Placement** 数据类型中，通过 **AvailabilityZone** 参数显式指定了可用区
+ 您使用 **SubnetId 参数**隐式指定了可用区

您既没有显式也没有隐式指定可用区，则请求会使用**区域级幂等性**。

### 可用区级幂等性
<a name="zonal-idempotency"></a>

可用区级幂等性确保 RunInstances API 请求在同一区域内的每个可用区中都是幂等的。这保证了在同一区域内，使用相同客户端令牌的请求在每个可用区中只能成功执行一次。然而，您仍然可以使用同一个客户端令牌在该区域的其他可用区中启动实例。

例如，如果您发送一个在 `us-east-1a` 可用区启动实例的幂等请求，然后在 `us-east-1b` 可用区再次使用相同的客户端令牌发起请求，我们会在这些可用区中分别启动实例。如果后续重试中的一个或多个参数发生变化，那么在这些可用区内使用相同客户端令牌进行的重试要么会成功返回但不执行任何操作，要么会因参数不匹配而报告 `IdempotentParameterMismatch` 错误。

### 区域级幂等性
<a name="regional-idempotency"></a>

区域级幂等性确保 RunInstances API 请求在同一区域内是幂等的。这保证了在同一区域内，使用相同客户端令牌的请求只能成功执行一次。然而，您可以使用完全相同的请求（包括相同的客户端令牌）在其他区域中启动实例。

例如，如果您发送一个在 `us-east-1` 区域启动实例的幂等请求，然后在 `eu-west-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（正常）  |  不重试  |  原始请求成功完成。成功返回任何后续重试。  | 
|  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/zh_cn/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 服务器端问题引起，通常是暂时性的。使用适当的退避策略重复发出请求。  | 