

# 멱등성 보장
<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

  클라이언트 토큰은 33\~126자(포함) 범위에서 최대 36자의 ASCII 문자일 수 있습니다.
+ CreateTaskSet

  클라이언트 토큰은 33\~126자(포함) 범위에서 최대 36자의 ASCII 문자일 수 있습니다.
+ RunTask

  클라이언트 토큰은 33\~126자(포함) 범위에서 최대 64자의 ASCII 문자일 수 있습니다.

**멱등성 유형**
+ 클러스터 - 같은 클러스터 내에서 동일한 토큰을 사용하는 요청은 멱등성을 가집니다. 예를 들어, ClientToken A는 클러스터 X의 `RunTask` 요청에 대한 요청 파라미터로 한 번만 사용할 수 있습니다. 다른 클러스터에 대한 `RunTask` 요청은 별도의 요청으로 간주됩니다. 따라서 클러스터 Y에 대한 `RunTask` 요청에 ClientToken A를 사용할 수 있습니다.

## RunTask의 멱등성
<a name="RunTaskIdempotency"></a>

`RunTask` API는 클라이언트 토큰을 사용하여 멱등성을 지원합니다. 클라이언트 토큰은 API 요청을 할 때 지정하는 고유 문자열입니다. 요청이 성공적으로 완료된 후 동일한 클라이언트 토큰과 동일한 요청 파라미터를 사용하여 API 요청을 다시 시도하면 원래 요청의 결과가 반환됩니다. 동일한 클라이언트 토큰을 사용하여 성공적인 요청을 재시도하는데, 리전 또는 가용 영역 외에 다른 파라미터 중 하나 이상이 다르면 `ConflictException`과 함께 재시도가 실패합니다. 고유 클라이언트 토큰을 지정하지 않으면 AWS SDK와 AWS Command Line Interface가 멱등성을 위해 요청에 대한 클라이언트 토큰을 자동으로 생성합니다. 클라이언트 토큰은 33\~126(포함) 범위의 최대 64자의 ASCII 문자를 포함하는 모든 문자열일 수 있습니다.

`RunTask` 클라이언트 토큰의 유효 기간(TTL)은 24시간입니다. 서로 다른 요청에 동일한 클라이언트 토큰을 재사용해서는 안 됩니다. 클라이언트 토큰 최대 TTL은 다음 두 값 중 더 작은 값 동안 유효합니다.
+ 24시간
+ 리소스 수명 \+ 1시간

  리소스의 수명은 태스크가 생성된 타임스탬프부터 마지막 상태(`lastStatus`)가 `STOPPED`로 전환된 타임스탬프까지입니다 `RunTask`를 사용하여 여러 태스크를 시작하는 경우 리소스 수명은 `STOPPED`로 변경된 마지막 태스크의 수명과 같습니다.

### RunTask 재시도 규칙 및 응답
<a name="retry-response"></a>

5xx 예외가 발생하여 요청을 재시도하면 재시도된 성공 응답에는 일반적으로 원래 요청이 반환했을 모든 정보가 포함됩니다. 중단된 지 1시간 미만인 태스크에는 태스크 ARN, 최종 상태 및 원하는 상태만 포함됩니다.

다음은 실행 중인 태스크 1개, 중지된 태스크 1개, 시작에 실패한 태스크 1개가 있는 경우 재시도 시 반환되는 응답의 예제 스니펫입니다.

```
{
  "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",
      ...
     }
  ]
}
```

1시간이 지난 실패에는 실패한 태스크 수만 포함됩니다.

## 예제
<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 OK | 다시 시도하지 않음 | 원래 요청이 성공적으로 완료되었습니다. 이후의 모든 재시도는 성공적으로 반환됩니다. | 
| 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/ko_kr/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 서버 측 문제로 인해 발생하며 일반적으로 일시적입니다. 적절한 백오프 전략으로 요청을 반복합니다. | 