v2 ECS 마이그레이션 테스트 결과 - 100-hours-a-week/KTB4-17th-wiki GitHub Wiki

1차 테스트 결과

70 message/s · 200 vu · 메시지 10만 건

지표 결과
테스트 조건 30분, 200명·1:1 채팅방 100개, 실제 10만 건 전송
종합 판정 FAIL
연결 전환 기존 사용자 100명 모두 Green 이동 성공
HTTP 성공 99,999건, 전환 중 실패 1건
중복 수신 1,450회

2차 테스트 결과

35 message/s · 200 vu · 메시지 6만 900건

지표 결과
HTTP 성공·DB 저장 60,899건, 전환 중 실패 1건
HTTP 전송 오류 1건
reload 구간 서버 RST 1건
온라인 상대방 메시지 미수신 0건
최종 메시지 누락 0건 — 재접속 중 놓친 13건은 이력 조회로 복구
WebSocket 중복 수신 0건

1건 실패의 원인

nginx reload 시 유휴 상태인 HTTP keep-alive 연결을 닫는 과정에서 발생한 경쟁 조건이다.

nginx는 해당 연결의 소켓을 닫고, OS는 FIN을 전송하며 TCP 종료 절차를 진행한다.

클라이언트는 연결 종료를 아직 인지하지 못한 상태에서 기존 연결로 POST 요청을 보낸다.

POST 패킷은 서버까지 도착하지만, 서버에서는 이미 해당 소켓을 닫았기 때문에 HTTP 요청으로 처리되지 않고 OS가 RST를 반환한다.

이번 요청은 Spring에 도달하지 않았고, 클라이언트의 재시도도 없어서 메시지가 저장되지 않았다.

해결 방법

nginx의 keepalive_min_timeout 설정을 주어서 해당 문제를 해결한다.

https://github.com/nginx/nginx/pull/456

3차 테스트 결과

지표 결과
HTTP 성공·DB 저장 60,900건 전부
HTTP 전송 오류 0건
reload 구간 서버 RST 0건
온라인 상대방 메시지 미수신 0건
최종 메시지 누락 0건
수신 지연 p95 14.67초
수신 지연 p99 36.36초
WebSocket 중복 수신 14건

과한 지연 시간의 원인

서버 처리량의 한계도 있겠지만, 블루-그린 전환 전에 DB에 rabbit_published 컬럼이 추가되고 Green으로 전환되는 사이에 쌓인 Outbox들이 Green 컨테이너에 순간적인 부하를 주기 때문에 안정화 전까지 지연 시간이 치솟는다.

해결 방법

nginx의 트래픽을 Green으로 보내기 직전에 DB 쿼리를 통해 동기화를 한 번 진행하자.

4차 테스트 결과

지표 결과
HTTP 성공·DB 저장 60,896건 — 전송 실패 4건
HTTP 전송 오류 4건 (ECONNRESET) — 모두 reload 이전 발생, DB 미저장
온라인 상대방 메시지 미수신 0건
최종 메시지 누락 0건
수신 지연 p95 2.16초
수신 지연 p99 13.89초
WebSocket 중복 수신 1건

4건 실패의 원인

nginx reload와 별개로, 75초 동안 사용하지 않은 HTTP keep-alive 연결을 종료하는 과정에서 경쟁 조건이 발생했다.

nginx가 FIN을 보낸 뒤, HTTP 클라이언트가 연결 종료를 처리하기 전에 기존 연결로 POST 요청을 보냈고 서버는 RST를 반환했다.

해당 요청들은 Spring에 도달하지 않았으며, 재시도가 없어 DB에 저장되지 않았다.

→ keep-alive 설정을 끄고 보내보자.


5차 테스트 결과

지표 결과
HTTP 성공·DB 저장 60,900건
HTTP 전송 오류 0건
온라인 상대방 메시지 미수신 0건
발송한 메시지의 최종 누락 0건
수신 지연 p95 2.24초
수신 지연 p99 16.87초
WebSocket 중복 수신 1건

참고자료

https://github.com/nginx/nginx/pull/456

https://nginx.org/en/docs/control.html#reconfiguration

새 워커 프로세스를 시작하고 기존 워커 프로세스에 정상적으로 종료하도록 요청하는 메시지를 보냅니다.
기존 워커 프로세스는 수신 소켓을 닫고 이전 클라이언트에 서비스를 계속 제공합니다.
모든 클라이언트에 대한 서비스가 완료되면 기존 워커 프로세스가 종료됩니다.

https://iximiuz.com/en/posts/reverse-proxy-http-keep-alive-and-502s/