NESTJS에서 동시성 테스트를 하던 도중, read econnreset 이 발생했다. 해결하려 많은 시간을 소비하여 이런 케이스를 가진 분들이 빠르게 해결했으면 좋겠어서, 해당 오류에 대한 해결법과 앞으로 이런 오류가 발생하고 해결한 뒤, 한 번쯤 생각해봐야 할 공부 리스트를 공유하려고 합니다.
0. 코드
- DB: Postgresql, Typeorm
- backend: nestjs
1. 문제점
코드를 작성하고 동시성 테스트를 진행하였다. 간단하게 설명하자면
- 특강 API로 선착순으로 100명을 받는다
- 따라서, 각기 다른 유저, 이메일로 총 100개의 Request로 만들고 들어온 순서에 맞게 처리해야 한다. 뒤에 들어온 5개의 요청은 100개로 한정해서 선착순으로 받기 때문에 5개는 실패 반환 처리를 해야 합니다.
- 그런데 여기서, 30~40개의 요청만 성공 요청이 되고, 뒤에 요청은 처리가 되지 않는 현상이 발생하게 됩니다.
- read econnreset 오류 발생
- 해당 오류에 대해서 검색해 봐도 정확히 판단(서버?, DB?, 운영체제?) 하기는 어려웠습니다
2. 해결법
저의 해결법은 이러했습니다.
1. 만약 TypeORM을 사용하고 있다면 설정값에서 connectTimeoutMS라는 값을 넣어 옵션을 넣어 원하는 TimeoutMS의 값을 수정하면 됩니다.
2. TypeORM을 사용하고 있지않고, 다른 방법을 찾아야 한다면 해당 DB에 ConnectionTime 설정을 찾아봐야 합니다.
위와 같은 설정 변경으로, 수정을 하고 connectTimeoutMS 부분을 넉넉하게 늘려줍니다. 그리고 나서 다시 e2e 테스트를 수행합니다.
100개의 요청이 20820ms로 많은 시간이 걸린 뒤에 해결되게 됩니다
3. 무슨 문제?
DB 마다 connectionTimout 기본값이 설정되어 있어 많은 요청에 있어 뒤에 있는 요청들이 timeout 문제가 발생된 문제점입니다.
그래서 DB에서는 기본적으로 설정해 놓은 timeout 시간으로 인해서, 요청 대기열에서 비교적 빠르게 들어온 요청들은 정해진 시간 안에 처리가 되고 나머지는 앞에 요청을 처리하는 데 걸린 시간에 의해서 대기열 뒤에 있는 요청에 대한 응답들은 Timeout 시켜서 뒤에 있던 해당 요청에 대한 응답이 없어 timeout이 발생하게 된 것입니다. 변경 결과, timeout 길이를 늘인 결과 맨 마지막 요청은 20820ms가 걸리고 나서야 요청을 받게 됩니다.
4. 앞으로
그런데 이게 과연 근본적으로 해결법일까요? 일단 시간이 오래 걸린 다는 것은 확인하게 되었습니다. 그리고 컴퓨팅 파워 문제도 아니었습니다. 그런데 생각해 보면 마지막 요청들에 대한 응답이 오래 걸리면 문제가 있습니다. 따라서 전체에 총량 시간도 중요하지만 각 요청마다 빠르게 응답하기 위해서는 오류는 해결했으니 앞으로 아래와 같은 방법들이 필요할 것 같습니다.
앞으로 해야 할 일
- 분산처리
- DB를 처리하는 부분을 로직을 최적화
- DB 락 부분을 많이 고려하여 사용
감사합니다.
----
그래도 위와 같은 방법으로 해결이 안된다면 node 버전을 18로 변경해보자