본 내용은 AWS EventBridge 사용시에 발생한 문제를 해결하는 과정을 다루고 있습니다. AWS EventBridge, Lambda, Firestore에 대한 기본적인 지식을 요하고 있습니다.
이번에 사용자가 Excel File을 업로드하면, Lambda, EventBridge, Firestore를 이용해서 Excel File의 정보들을 Database에 넣어주는 기능을 개발하게 되었는데, 이때 발생한 이슈가 있어서 공유하고자 글을 남깁니다.
바로 한번 수행에 100회 미만의 읽기가 발생해야 하는 로직을 10번 미만으로 수행했는데, Firestore에 일일 제한 읽기 횟수인 50000만회를 채우는 일이 발생한 것이었습니다. 😇
해당 Issue는 다행히 Firestore를 유료 플랜으로 결제하지 않은 상태라서 비용적인 문제는 발생하지 않았지만,
만약 Firestore를 유료플랜으로 결제했다면 큰 비용 손실이 있었을 건으로 간주되었고, 그래서 중요도를 높게 선정해서 Hotfix로 처리하고자 하였습니다.
먼저 문제를 분석 하기 전, 어떤 기능이었는지 간단하게 살펴보도록 하겠습니다.
그럼 이제 어디에서 문제가 발생했는지 차근차근 분석해보도록 하겠습니다.
가장 먼저 문제가 발생했던 Fire Store 읽기 횟수 초과에 대해서 알아보면, 특정 시간을 기점으로, 읽기 횟수가 계속 증가하고, 결국 최대 한도까지 도달하는 것을 알 수 있었고, 스냅샷 리스너를 통해서, 어떠한 요청이 Firestore에 계속 발생하고 있다는 것도 알 수 있었습니다.
표 이해를 위해 밑에 설명을 추가했습니다.
그러니까 Firestore에 정보를 요약하자면, FireStore에 저장된 정보들을 연결된 Lambda가 계속 읽고 있다는 것이다. 심지어 사용자 수가 계속 늘어나기까지 하는 것을 알 수 있습니다..
하지만 나는 FireStore에 저장된 데이터를 가져와서 WAS에 보내주고 나서는 저장된 데이터를 이벤트를 종료하도록 설정해놨는데 왜 이런일이 생겼을까요?
Firestore 정보를 분석해본 결과, 이벤트가 꺼지지 않아 Lambda가 계속 실행된다는 것을 의미하므로 AWS Lambda를 분석 해보도록 하겠습니다.
Log 분석
로그 및 정보들을 제공할 수는 없지만, AWS Lambda의 Log들을 분석해본 결과 Lambda에 시간초과가 발생해서 정상적으로 종료되지 않는다는 것을 알 수 있었습니다.
정상적인 종료가 이루어지지 않기 때문에 Lambda 끝에 설정한, 저장된 Document 삭제 로직과 이벤트 삭제 로직이 동작하지 않았던 것입니다. 🤪
그리고 정상적인 종료가 이루어지지 않는 Lambda는, 재시작되고 있었습니다. 이로 인해 이벤트가 활성화되면 람다가 동작하는데 람다가 예기치 않는 오류로 종료되고 다시 시작하고, 이벤트가 꺼지지 않았으므로 이벤트에 의해 Lambda는 또 시작되고 ... 이렇게 반복되면서 FireStore에 읽기 횟수를 초과하게 되는 것입니다.
예를 들어서, Lambda 시간제한이 1분, Event는 3분에 한번씩 람다를 키도록 설정해놓고, Lambda가 1분 시간초과를 발생시킨다면
Event로 첫 람다가 시작되고, 15분이 지나면 동일한 Lambda가 6개 켜지고, 각각의 람다는 또 실패하고 다시 켜지는 과정을 반복하게 될 것입니다.
그럼 이제 Lambda code를 분석해보도록 하겠습니다.
Lambda 분석
전체 코드를 제공할 수는 없지만 문제가 된 부분은 다음 부분입니다.
const result = await Promise.all(funcs);
해당 Promise.all() 는 비동기 병렬처리를 하는 함수입니다. Lambda에서 Promise.all()을 사용하는 경우에는 몇가지 고려할 사항이 있는데, 그 내용은 다음과 같습니다.
제 경우는 해당 Promise.all() 실행 시, 최대 100개의 요청을 만들어서 WAS로 요청을 보내고 있었고, 이 때 시간 제한에 걸려 중간에 강제로 종료 되었던 것 입니다.
이번 Trouble Shooting에서 알게된 핵심 문제는,
Lambda의 Timeout시에는 예외처리 및 종료 시 처리하는 함수가 동작하지 않는다는 것입니다.
그리고 추가적으로 알게 된 주요 내용은,
는 것을 알게 되었습니다.
그 외에도 문제를 살펴보며, Lambda, EventBridge, Firestore에 더 자세하게 알게 되었습니다. 😇
HotFix였으므로, 지금 당장의 문제를 해결하는 방법은 다음과 같습니다.
- Lambda의 Timeout 시간 증가
Lambda의 Timeout 시간을 1분에서 3분으로 증가시켰습니다.
- Lambda 병렬 처리를 취소.
Lambda 코드를 수정을 통해 병렬로 수행하던 코드를 병렬로 처리하지 않도록 변경시켰습니다. 그래서 시간초과 오류가 발생하더라도, 수행한 부분까지 firestore의 document가 감소되어, 남은 부분부터 다시 요청 처리를 할 수 있으므로, 같은 읽기를 반복하지 않도록 했습니다.
HotFix이므로, 일단 문제를 해결했지만, 추가적으로 더 찾아보고 적용할 내용들은 다음과 같습니다.
EventBridge 실행 시 조건 설정
Lambda 갯수 제한하기