2024. 6. 3. 19:04ㆍ프로젝트/[EATceed] 몸무게 증량 어플
프로젝트를 진행하며 배포 직후 회원 가입 요청에서 request time out이 몇 번이고 발생하였습니다.
(몇 번 요청한 이후에는 발생하지 않았다.)
이에 대한 원인은 무엇일까?
배포 직후라는 점에서 JVM의 동작 방식과 관련이 있을 수 있습니다. 또한, 제가 작성한 코드 안에서 병목 지점이 있을 수 있습니다.
그것도 아니라면, 인프라상에 문제가 있을 수도 있습니다.
이번 포스팅에서는 Request Time Out 문제를 해결하기 위해 인프라에서 시도한 것들에 대해서 이야기하겠습니다.
현재 인프라에서 Request Time Out 응답이 오는 케이스를 생각해보면, 아래와 같을 것입니다.
첫 번째, 애플리케이션에서 해당 API 처리가 지연된 경우 해당 서버의 TimeOut 시간을 초과해 애플리케이션에서 ALB로 Request Time Out을 보내는 경우.
두 번째, ALB의 Connection idle timeout 시간을 초과하여 ALB에서 Connection을 닫아버린 경우.
제 경우에는 인프라와 애플리케이션 모두 문제가 있었습니다... 🥹
(포스팅 아래에는 애플리케이션 관련한 문제를 해결한 포스팅의 링크가 있습니다.)
Request Time Out은 왜 발생하는 것일까?
Request Time Out이 발생하기 위한 전제는 해당 API를 요청하였을 때 응답시간이 Server 필자는 Spring Boot를 사용하기 때문에 Tomcat의 Connection Timeout 기간보다 오래 걸리는 것입니다.
필자의 코드는 부끄럽게도... 해당 경우를 통과(?)하였기 때문에 해당 이슈가 발생하였습니다.
여기서 질문! Tomcat의 Connection Timeout은 몇 초일까요?
공식문서에 따르면, connectionTimeout의 default는 60s라고 합니다.
https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
즉, 배포 직후 회원가입 API 호출이 60s 이상 걸렸던 것입니다.. 😰
그러면, Request Tiimeout이란 응답은 어떻게 전해지게 되는 걸까?
먼저, 로드 밸런서부터 살펴보겠습니다.
요청을 처리할 때 로드 밸런서는 클라이언트의 연결과 타겟과의 연결, 두 가지 연결을 유지합니다.
로드 밸런서와 클라이언트 간의 연결은 프론트엔트 연결이라고 하며, 로드 밸런서와 타겟간의 연결은 백엔드 연결이라 합니다.
당연하게도 Connection은 무한정 연결할 수는 없습니다. 그래서, Application Load Balancer에서는 Connection Idle Timeout을 설정할 수가 있습니다.
Connection Idle Timeout이란 Client와 Server간의 연결이 일정 시간 동안 비활성 상태일 때 해당 연결을 자동으로 종료하는 시간 제한 설정입니다.
즉, 특정 시간이 지나면 ALB와 Target Group의 Connection을 끊어버립니다.
필자의 ALB의 Connection idle timeout이 60초, Tomcat의 connection time out 시간은 60초였습니다.(기본값 사용)
따라서, 60s내에 Server에서 요청을 처리하지 않으면 Server 에서 ALB로 Timout 응답을 보내고 ALB에서도 60s가 지나면 Server와 Client Connection을 끊어버린 것이었습니다.
그래서 배포 직후에 Request Time Out 응답을 받았던 것이었습니다.
권고사항
AWS에서는 ALB의 idle timeout 시간을 Server(여기서는 Tomcat)의 connection timeout 시간보다 길게 설정할 것을 권고하고 있습니다.
ALB의 idle timeout 시간을 Server의 connection timeout 시간보다 길게 설정할 경우를 생각해봅시다.
Server가 connection timeout이 발생해 ALB에게 Request Time Out 응답을 보내고 ALB는 다시 Client에게 Request Time Out 응답을 보내게 됩니다. 하지만, ALB의 idle timeout 시간은 connection timeout 시간보다 길기 때문에 ALB는 아직 Server와 Connection이 남아있는 것으로 파악할 수 있습니다.
이에 남은 시간동안 요청을 계속 보내게 되고 Client는 계속 Request Time Out 응답을 받을 수 있습니다.
ALB가 Connection Idle timeout을 사용하는 이유
ALB에서 Connection idle timeout을 설정하는 이유는 로드 밸런서의 성능을 최적화하기 위해서이다. 즉, 안 쓸 때는 연결을 끊어버려 자원을 아끼는 것이다.
번외) Health Check가 있는 이유
만약 응답 지연으로 EC2와 ALB의 Connection이 끊겼을 경우 Health Check를 통해 ALB는 해당 EC2가 사용할 수 있는 지의 여부를 확인할 수 있다. Health Check를 한다해서 Connection이 연결되는 것이 아니라 단지 EC2가 사용할 수 있는 서버인지 확인하는 것뿐이니다
회고
해당 이슈를 트러블슈팅하면서 ALB의 idle time out 옵션 뿐만아니라 Tomcat의 설정까지 살펴볼 수 있는 좋은 기회였다.
참고)
애플리케이션 API 응답 지연 해결 : 이메일 보낼 시 @Async를 사용하여 비동기 + 논 블락킹으로 처리하여 응답 속도 개선
https://rasony.tistory.com/200
'프로젝트 > [EATceed] 몸무게 증량 어플' 카테고리의 다른 글
통합 테스트에 테스트컨테이너 도입 (0) | 2024.06.25 |
---|---|
Spring Event와 @Aysnc를 사용해 회원가입 개선 (0) | 2024.06.09 |
전략 패턴을 이용해서 요구사항 대응하기 (0) | 2024.06.01 |
CI/CD 파이프라인 구축 (0) | 2024.05.26 |
EC2 용량 부족 이슈 해결 (0) | 2024.05.13 |