QMAws::runTask | error occurred during run ecs task - {
RCA: QMAws::runTask | ThrottlingException: Rate exceeded
Error Log#
QMAws::runTask | error occurred during run ecs task - {
name: 'ThrottlingException',
message: 'Rate exceeded',
stack: 'ThrottlingException: Rate exceeded
at Request.extractError (/tmp/agent/dist/node_modules/aws-sdk/lib/protocol/json.js:80:27)
at Request.callListeners (/tmp/agent/dist/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
...'
}
Impact#
- Service:
cupixworks-any-compute-agent - Team: arthtech
- 발생 횟수: 40
- 최초 발생: 2026-04-06T08:26:36.918Z
- 최근 발생: 2026-04-07T10:00:43.675Z
Root Cause Summary#
cupixworks-any-compute-agent의 QMAws 클래스가 AWS ECS API를 호출할 때, AWS SDK 클라이언트에 maxRetries 및 retryDelayOptions를 설정하지 않아 SDK 기본 retry 정책(짧은 간격, exponential backoff 미적용)이 사용됩니다. 동시에, JobManager::checkingQueue가 SQS에서 수신한 메시지를 500ms 간격으로 순차 처리하면서 다수의 ECS listContainerInstances, describeContainerInstances, startTask API 호출을 짧은 시간에 집중 발생시킵니다. 여러 job이 동시에 대기 중일 때 1분 내에 17건 이상의 runTask begin 호출이 발생하여 AWS ECS API rate limit을 초과하고, ThrottlingException: Rate exceeded 에러가 발생합니다.
Technical Analysis#
Code Path#
- Entry point:
job.manager.ts:37—checkingQueue메서드가 SQS 메시지 수신 후 job 실행 job.manager.ts:72-77—runJobs가 job 목록을 순차 실행하되 API 호출 간 rate limiting 없음job.manager.ts:99—_qmAws.runTask()호출qmAws.ts:117-168—runTask메서드 내에서listContainerInstances→describeContainerInstances→startTask순서로 ECS API 3회 연속 호출- Failure point:
qmAws.ts:164-167— ECS API 호출 중ThrottlingException발생 시 catch 블록에서 에러 로깅 후 빈 배열 반환
// packages/cupix-tesla-compute-agent/src/model/qmAws.ts:6-23
export class QMAws {
constructor(
readonly awsRegion: string,
readonly queueName: string
) {
AWS.config.update({ region: awsRegion });
this._sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
this._ecs = new AWS.ECS({ apiVersion: '2014-11-13' }); // maxRetries 미설정
this._autoScaling = new AWS.AutoScaling({ apiVersion: '2011-01-01' });
}
비교: AwsEcsManager(base 패키지)는 올바르게 설정되어 있음:
// packages/base/src/manager/aws-ecs.manager.ts:21-25
this._ecs = new AWS.ECS({
apiVersion: '2014-11-13',
maxRetries: Constants.MaxRetries, // 5회
retryDelayOptions: {base: Constants.RetryInterval} // 10000ms
});
JobManager::checkingQueue는 메시지가 있으면 500ms sleep 후 즉시 재귀 호출하여, 대기 중인 job이 많을 때 API 호출이 폭주합니다:
// packages/cupix-tesla-compute-agent/src/manager/job.manager.ts:37-50
private checkingQueue = async (_gmAws: QMAws) => {
const messages = await _gmAws.receiveMessage();
if (messages.length > 0) {
const _jobList = this.createJobFromMessages(messages);
await this.runJobs(_jobList, _gmAws);
await CPUtils.sleep(500); // 500ms만 대기 후 즉시 다음 batch
await this.checkingQueue(_gmAws); // 재귀 호출
} else {
// 메시지 없을 때만 10초 interval
_gmAws.intervalTimer = setTimeout(() => {
this.checkingQueue(_gmAws);
}, Constants.CheckQueueInterval);
}
};
runTask 메서드는 한 번의 호출에서 최대 3개의 ECS API를 순차 호출합니다:
// packages/cupix-tesla-compute-agent/src/model/qmAws.ts:117-168
runTask = async (awsClusterName: string, job: QMJob, instanceType: string) => {
try {
const containerInstanceArns = await this.listContainerInstances(awsClusterName, instanceType); // API 1
// ...
const containerInstances = await this.describeContainerInstances(awsClusterName, containerInstanceArns); // API 2
for await (const containerInstance of containerInstances) {
// ...
tasks = await this.startTask(awsClusterName, containerInstance.containerInstanceArn, job); // API 3 (반복)
}
} catch (error) {
logger.error('QMAws::runTask | error occurred during run ecs task - %s', error); // 여기서 에러 발생
return [];
}
};
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-any-compute-agent status:error "ThrottlingException"
service:cupixworks-any-compute-agent "runTask" "begin"
에러 버스트 패턴 (2026-04-07 18:08 KST / 09:08 UTC)
1분 내에 동일 job들이 반복적으로 runTask를 시도하며 ThrottlingException 발생:
18:08:17 KST QMAws::runTask | begin - job id: 5835, task def: cupix-capture-refinement-production-arm, instance_type: m7g.8xlarge, launch_mode: CUPIXWORKS
18:08:18 KST QMAws::runTask | begin - job id: 5836, ...
18:08:19 KST QMAws::runTask | begin - job id: 5837, ...
18:08:20 KST QMAws::runTask | begin - job id: 5838, ...
18:08:20 KST QMAws::runTask | begin - job id: 174389, task def: cupix-pano-postprocessor-production, instance_type: g6.2xlarge
18:08:21 KST QMAws::runTask | begin - job id: 174390, task def: cupix-pano-postprocessor-production, instance_type: g6.2xlarge
18:08:21 KST QMAws::runTask | begin - job id: 5839, ...
--- ThrottlingException errors ---
18:08:18 KST QMAws::runTask | error occurred during run ecs task - { name: 'ThrottlingException', message: 'Rate exceeded' }
18:08:22 KST QMAws::runTask | error occurred during run ecs task - { name: 'ThrottlingException', message: 'Rate exceeded' }
18:08:33 KST QMAws::runTask | error occurred during run ecs task - { name: 'ThrottlingException', message: 'Rate exceeded' }
18:08:36 KST QMAws::runTask | error occurred during run ecs task - { name: 'ThrottlingException', message: 'Rate exceeded' }
--- 실패한 job들이 재시도 ---
18:08:32 KST QMAws::runTask | begin - job id: 5836, ... (2nd attempt)
18:08:33 KST QMAws::runTask | begin - job id: 5837, ... (2nd attempt)
18:08:34 KST QMAws::runTask | begin - job id: 5838, ... (2nd attempt)
18:08:35 KST QMAws::runTask | begin - job id: 5835, ... (2nd attempt)
18:08:36 KST QMAws::runTask | begin - job id: 5839, ... (2nd attempt)
7개 job이 4초 내에 시작되어 각각 최소 3개의 ECS API(listContainerInstances, describeContainerInstances, startTask)를 호출하므로, 4초 동안 ~21개 이상의 ECS API 호출이 발생합니다. ThrottlingException 후 재시도가 이어지면서 추가 API 호출이 누적됩니다.
Retry 로그 (SDK 기본 retry 또는 application-level retry):
2026-04-07T10:09:28.865Z Attempt 1: Waiting 1000 ms before retrying...
2026-04-07T10:15:09.550Z Attempt 1: Waiting 1000 ms before retrying...
2026-04-07T10:19:04.876Z Retrying in 100ms...
2026-04-07T10:20:59.767Z Retrying in 100ms...
100ms~1000ms의 짧은 retry 간격은 throttling 상황을 악화시킵니다.
3개 SQS 큐 동시 폴링: JobManager는 3개의 QMAws 인스턴스(기본, ARM, GPU)를 생성하여 동시에 큐를 폴링합니다 (job.manager.ts:14-17). 세 큐에 동시에 메시지가 있으면 ECS API 호출량이 3배로 증가합니다.
Fix Recommendation#
즉시 조치 (Critical)#
packages/cupix-tesla-compute-agent/src/model/qmAws.ts:21—AWS.ECS생성자에maxRetries와retryDelayOptions를 추가하여 base 패키지의AwsEcsManager와 동일한 설정 적용.maxRetries: 5,retryDelayOptions: { base: 10000 }(shared-config의MaxRetries,RetryInterval상수 사용).
단기 개선 (1주 이내)#
job.manager.ts:72-77—runJobs메서드에서 각 job 실행 사이에 최소 1-2초의 delay를 추가하거나, token bucket 패턴으로 ECS API 호출 속도를 제한.job.manager.ts:42—checkingQueue의 재귀 호출 전 sleep을 500ms에서 2-3초로 증가시켜 burst 완화.qmAws.ts:117—runTask메서드에 ThrottlingException 감지 시 exponential backoff를 적용한 application-level retry 로직 추가.
장기 개선 (재발 방지)#
QMAws클래스를 base 패키지의AwsEcsManager패턴으로 리팩토링하여 AWS SDK 설정을 일관되게 관리. 현재 compute-agent만 독자적인QMAws클래스를 사용하고 있어 설정 불일치가 발생.- ECS API 호출에 대한 centralized rate limiter 도입 (예: p-throttle 또는 bottleneck 라이브러리). 3개 큐의 호출을 하나의 rate limiter로 통합.
- 대량 job 처리 시 ECS RunTask의
count파라미터를 활용하여 단일 API 호출로 여러 task를 시작하는 방식으로 전환 (현재startTask는 job당 1개 task만 시작).
Monitoring#
- ECS API ThrottlingException 발생 빈도 추적:
service:cupixworks-any-compute-agent status:error "ThrottlingException"
- runTask 호출 빈도 모니터링 (분당 호출 수):
service:cupixworks-any-compute-agent "QMAws::runTask | begin"
- 1분 내 runTask begin 횟수가 10회 초과 시 알림 설정 권장.
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard — SDK 설정 변경은 trivial이나, rate limiting 도입은 테스트가 필요한 standard 수준의 작업