

# 确保幂等性
<a name="ECS_Idempotency"></a>

执行变异操作时，您可能会看到异常，这是因为资源变异后出现超时或服务器问题。这样就很难确定是否发生了变异，并且会导致多次重试操作。但是，如果原始操作和随后的重试实际上执行了变异，则您可能已经应用了叠加更改或者创建了超出预期的额外资源。幂等性可确保操作对资源进行的变异不超过一次。对于幂等性请求，如果原始请求成功变异，则后续重试也会成功完成，而不会执行任何后续变异。

**Topics**
+ [Amazon ECS 中的幂等性](#client-tokens)
+ [RunTask 请求的幂等性](#RunTaskIdempotency)
+ [示例](#Run_Task_Idempotency_CLI)
+ [针对幂等请求的重试建议](#recommended-actions)

## Amazon ECS 中的幂等性
<a name="client-tokens"></a>

以下 API 操作通过*客户端令牌*来支持幂等性（可选）。对应的 AWS CLI 命令同样支持通过客户端令牌实现幂等性。客户端令牌是一个区分大小写的唯一字符串。要让这些操作的 API 请求具备幂等性，请在请求中指定一个客户端令牌。您不应将同一个客户端令牌用于其他 API 请求。如果您使用相同的客户端令牌并保持所有参数一致来重试一个已成功完成的请求，该重试会直接成功，而不会执行任何额外操作。

**使用客户端令牌实现幂等性的操作**
+ CreateService

  客户端令牌最多可以包含 36 个 ASCII 字符，字符的 ASCII 码值在 33-126（含）之间。
+ CreateTaskSet

  客户端令牌最多可以包含 36 个 ASCII 字符，字符的 ASCII 码值在 33-126（含）之间。
+ RunTask

  客户端令牌最多可以包含 64 个 ASCII 字符，字符的 ASCII 码值在 33-126（含）之间。

**幂等性类型**
+ 集群：在同一集群中使用相同令牌的请求具有幂等性。例如，对于集群 X 中的 `RunTask` 请求，ClientToken A 作为请求参数只能使用一次。`RunTask` 向其他集群发出的请求视为单独的请求。因此，集群 X 中的 `RunTask` 请求可以使用 ClientToken A。

## RunTask 请求的幂等性
<a name="RunTaskIdempotency"></a>

`RunTask` API 使用客户端令牌支持幂等性。客户端令牌是您在发出 API 请求时指定的唯一字符串。如果在某个 API 请求成功完成后，您使用相同的客户端令牌和相同的请求参数重试该请求，则返回原始请求的结果。如果您在重试成功的请求时使用了相同的客户端令牌，但一个或多个参数发生变化（区域或可用区除外），重试将失败，并返回 `ConflictException`。如果您没有指定自己的客户端令牌，AWS 开发工具包和 AWS Command Line Interface 会自动为请求生成客户端令牌，以确保其幂等性。客户端令牌可以是包含最多 64 个 ASCII 字符的任意字符串，字符的 ASCII 码值在 33 到 126（含）之间。

`RunTask` 客户端令牌的生存时间（TTL）为 24 小时。您不应为不同的请求重复使用相同的客户端令牌。客户端令牌的最大 TTL 以下面两个值中的较小值为准：
+ 24 小时
+ 资源生命周期加上一小时

  资源生命周期是指创建任务的时间戳到最后一个状态 (`lastStatus`) 转换为 `STOPPED` 的时间戳。当使用 `RunTask` 启动多个任务时，资源的生命周期等于状态转换为 `STOPPED` 的最后一个任务的生命周期。

### RunTask 重试规则和响应
<a name="retry-response"></a>

当您因为收到“5xx”异常而重新尝试请求时，重试后的成功响应通常包含原始请求本应返回的所有信息。停止时间不到一小时的任务仅包括任务 ARN、最后状态和所需状态。

以下是一个重试响应的示例代码片段，其中包含一个正在运行的任务、一个已停止的任务以及一个启动失败的任务。

```
{
  "failures": [
    {
      "arn": "arn:aws:ecs:us-east-1:123456789012:container/4df26bb4-f057-467b-a079-961675296e64",
      "reason": "RESOURCE:MEMORY"
    }
  ],
  "tasks": [
    {
      "desiredStatus": "RUNNING",
      "taskArn": "arn:aws:ecs:us-east-1:123456789012:task/default/fdf2c302-468c-4e55-b884-5331d816e7fb",
      ...
    },
    {
      "taskArn": "arn:aws:ecs:us-east-1:123456789012:task/default/fdf2c302-468c-4e55-b884-5331d819999",
      "lastStatus": "STOPPED",
      ...
     }
  ]
}
```

如果失败超过一小时，则仅包括失败的任务数。

## 示例
<a name="Run_Task_Idempotency_CLI"></a>

### AWS CLI 命令示例
<a name="cli-example"></a>

要使 AWS CLI 命令具备幂等性，请添加 `--client-token` 选项。

**示例：create-service**  
以下 [create-service](https://docs.aws.amazon.com/cli/latest/reference/ecs/create-service.html#examples) 命令通过包含客户端令牌而具备幂等性。

```
aws ecs create-service \
    --cluster MyCluster \
    --service MyService \
    --task-definition MyTaskDefinition:2 \
    --desired-count 2 \
    --launch-type FARGATE \
    --platform-version LATEST \
    --network-configuration "awsvpcConfiguration={subnets=["subnet-12344321"],securityGroups=["sg-12344321"],assignPublicIp="ENABLED"}" \
    --client-token 550e8400-e29b-41d4-a716-44665544
```

**示例：create-task-set**  
以下 [create-task-set](https://docs.aws.amazon.com/cli/latest/reference/ecs/create-task-set.html#examples) 命令通过包含客户端令牌而具备幂等性。

```
aws ecs create-task-set \
    --cluster MyCluster \
    --service MyService \
    --task-definition MyTaskDefinition:2 \
    --network-configuration "awsvpcConfiguration={subnets=["subnet-12344321"],securityGroups=["sg-12344321"]}" \
    --client-token 550e8400-e29b-41d4-a716-44665544
```

**示例：run-task**  
以下 [run-task](https://docs.aws.amazon.com/cli/latest/reference/ecs/run-task.html#examples) 命令通过包含客户端令牌而具备幂等性。

```
aws ecs run-task \
    --cluster MyCluster \
    --task-definition MyTaskDefinition:2 \
    --client-token 550e8400-e29b-41d4-a716-446655440000
```

### API 请求示例
<a name="api-example"></a>

要使 API 请求具有幂等性，请添加 `clientToken` 参数。

**示例：CreateService**  
以下 [CreateService](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateService.html) API 请求通过包含客户端令牌而具备幂等性。

```
POST / HTTP/1.1
Host: ecs.us-east-1.amazonaws.com
Accept-Encoding: identity
Content-Length: 87
X-Amz-Target: AmazonEC2ContainerServiceV20141113.CreateService
X-Amz-Date: 20150429T170125Z
Content-Type: application/x-amz-json-1.1
Authorization: AUTHPARAMS

{
  "serviceName": "MyService",
  "taskDefinition": "MyTaskDefinition:2",
  "desiredCount": 10,
   "capacityProviderStrategy": [ 
      { 
         "base": "number",
         "capacityProvider": "FARGATE",
         "weight": 1
      }
   ],
   "capacityProviderStrategy": [ 
      { 
         "base": "number",
         "capacityProvider": "FARGATE_SPOT",
         "weight": 1
      }
   ],
   "clientToken": "550e8400-e29b-41d4-a716-44665544"
}
```

**示例：CreateTaskSet**  
以下 [CreateTaskSet](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html) API 请求通过包含客户端令牌而具备幂等性。

```
POST / HTTP/1.1
Host: ecs.us-east-1.amazonaws.com
Accept-Encoding: identity
Content-Length: 87
X-Amz-Target: AmazonEC2ContainerServiceV20141113.CreateTaskSet
X-Amz-Date: 20150429T170125Z
Content-Type: application/x-amz-json-1.1
Authorization: AUTHPARAMS

{
  "serviceName": "MyService",
  "taskDefinition": "mytask:1",
  "desiredCount": 1,
   "capacityProviderStrategy": [ 
      { 
         "base": "number",
         "capacityProvider": "FARGATE",
         "weight": 1
      }
   ],
   "capacityProviderStrategy": [ 
      { 
         "base": "number",
         "capacityProvider": "FARGATE_SPOT",
         "weight": 1
      }
   ],
    "clientToken": "550e8400-e29b-41d4-a716-44665544" 
}
```

**示例：RunTask**  
以下 [RunTask](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RunTask.html) API 请求通过包含客户端令牌而具备幂等性。

```
POST / HTTP/1.1
Host: ecs.us-east-1.amazonaws.com
Accept-Encoding: identity
Content-Length: 45
X-Amz-Target: AmazonEC2ContainerServiceV20141113.RunTask
X-Amz-Date: 20161121T215740Z
User-Agent: aws-cli/1.11.13 Python/2.7.12 Darwin/16.1.0 botocore/1.4.66
Content-Type: application/x-amz-json-1.1
Authorization: AUTHPARAMS

{
  "count": 1,
  "taskDefinition": "mytask:1",
  "clientToken": "550e8400-e29b-41d4-a716-446655440000" 
}
```

## 针对幂等请求的重试建议
<a name="recommended-actions"></a>

下表显示了幂等性 API 请求可能获得的一些常见响应，并提供了重试建议。


| 响应 | 建议 | 评论 | 
| --- | --- | --- | 
| 200（正常） | 不重试 | 原始请求成功完成。成功返回任何后续重试。 | 
| 400 系列响应代码（[客户端错误](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/errors-overview.html#CommonErrors)） | 不重试 | 请求存在问题，原因如下：[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/ECS_Idempotency.html)<br />如果请求涉及正在改变状态的资源，则重试请求可能会成功。 | 
| 500 系列响应代码（[服务器端错误](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/errors-overview.html#api-error-codes-table-server)） | 重试 | 该错误是由 AWS 服务器端问题引起，通常是暂时性的。使用适当的退避策略重复发出请求。 | 