본문 바로가기
N8N 워크플로우 N8N 워크플로우

메시지 재시도가 Backpressure를 가속하는 메커니즘

읽는 시간 약 8분
eba994ec8b9ceca780 ec9eacec8b9ceb8f84eab080 backpressureeba5bc eab080ec868ded9598eb8a94 eba994ecbba4eb8b88eca698 1791292461

장애를 복구하려던 재시도가 왜 시스템을 더 느리게 만들었을까

메시지 재시도가 Backpressure를 가속하는 메커니즘

분산 시스템에서 재시도(Retry)는 가장 흔하게 사용하는 장애 복구 전략이다. 네트워크 오류나 일시적인 서비스 장애가 발생했을 때 요청을 다시 보내면 정상 처리되는 경우가 많기 때문이다. 그래서 많은 개발자들은 재시도를 시스템 안정성을 높이는 안전장치로 생각한다.

하지만 실제 운영 환경에서는 정반대의 상황이 자주 발생한다. 장애가 발생한 순간 수많은 서비스가 동시에 재시도를 시작하면서 원래의 장애보다 더 큰 부하가 만들어지는 것이다. 이때 발생하는 대표적인 현상이 바로 Backpressure 증폭이다.

Backpressure는 시스템이 처리 가능한 속도보다 더 많은 요청이 유입될 때 발생하는 흐름 제어 메커니즘이다. 문제는 재시도가 이 흐름 제어를 무력화하면서 장애를 시스템 전체로 확산시킨다는 점이다.


재시도가 Backpressure를 증폭시키는 과정

많은 장애는 다음과 같은 순서로 전개된다.

1단계: 특정 서비스의 처리 속도 저하

데이터베이스 응답이 느려지거나 외부 API 장애가 발생한다.

그 결과 서비스 응답 시간이 증가한다.

2단계: 요청 대기열 증가

처리가 늦어지면서 Queue가 빠르게 쌓인다.

Worker는 기존 작업을 처리하느라 바빠지고 새로운 요청은 대기 상태에 들어간다.

3단계: 타임아웃 발생

상위 서비스는 응답을 기다리다가 타임아웃을 발생시킨다.

문제는 이 시점에 실제 작업이 끝난 것이 아니라는 점이다.

하위 시스템은 여전히 해당 요청을 처리 중일 수 있다.

4단계: 재시도 시작

상위 서비스는 실패로 판단하고 동일 요청을 다시 전송한다.

기존 요청이 아직 처리 중인데 새로운 요청까지 추가되는 상황이 발생한다.

5단계: 부하 증폭

100개의 요청이 실패해 모두 재시도된다면 시스템은 순식간에 200개의 요청을 처리해야 한다.

재시도가 반복될수록 부하는 기하급수적으로 증가한다.


실제 운영 환경에서 발생하는 Retry Storm

실무에서 가장 위험한 상황은 Retry Storm(재시도 폭풍)이다.

예를 들어 5개의 서비스가 하나의 데이터베이스를 사용한다고 가정해보자.

  • 서비스 A : 재시도 3회
  • 서비스 B : 재시도 3회
  • 서비스 C : 재시도 5회
  • 서비스 D : 재시도 3회
  • 서비스 E : 재시도 5회

데이터베이스 응답 속도가 느려지는 순간 모든 서비스가 동시에 재시도를 시작한다.

원래 초당 1,000건의 요청이 들어오던 환경이 순식간에 3,000~5,000건 수준으로 증가할 수 있다.

장애 원인은 데이터베이스의 일시적인 지연이었지만 실제 장애 규모는 재시도 로직에 의해 수 배 이상 확대된다.


재시도가 Queue 적체를 악화시키는 이유

재시도 요청도 결국 Queue로 들어간다.

즉 시스템 입장에서는 신규 요청과 재시도 요청을 구분하지 못한다.

결과적으로 Queue에는 다음이 동시에 존재한다.

  • 신규 사용자 요청
  • 타임아웃된 기존 요청
  • 재시도 요청
  • 중복 재시도 요청

이 상황이 지속되면 Queue 길이가 급격하게 증가한다.

Queue 적체가 발생하면 다음 문제가 연쇄적으로 발생한다.

  • Worker Latency 증가
  • Connection Pool 고갈
  • Thread Pool 포화
  • API Timeout 증가
  • 추가 재시도 발생

결국 Backpressure가 더욱 강해지는 악순환이 시작된다.


흔히 하는 실수

재시도 횟수를 늘리면 성공 확률이 높아진다

일부 상황에서는 맞지만 과부하 상황에서는 틀린 이야기다.

이미 처리 능력이 한계에 도달한 시스템에 더 많은 요청을 보내는 것은 문제를 해결하지 못한다.

오히려 복구 시간을 늘리는 결과를 만든다.

모든 오류는 재시도해야 한다

400번대 오류는 대부분 잘못된 요청이다.

이 경우 재시도해도 결과는 동일하다.

재시도는 다음과 같은 상황에만 적용하는 것이 일반적이다.

  • 네트워크 오류
  • 일시적인 서버 장애
  • 일시적인 연결 실패
  • 일시적인 타임아웃

Backpressure를 줄이는 재시도 전략

지수 백오프 적용

재시도 간격을 점진적으로 늘린다.

예시

  • 1차 재시도 : 1초
  • 2차 재시도 : 2초
  • 3차 재시도 : 4초
  • 4차 재시도 : 8초

이를 통해 시스템이 회복할 시간을 확보할 수 있다.

Jitter 추가

모든 클라이언트가 동일한 시점에 재시도하는 것을 방지한다.

랜덤한 지연 시간을 추가하면 트래픽이 분산된다.

최대 재시도 횟수 제한

무한 재시도는 절대 금물이다.

일반적으로 3~5회 이내로 제한하는 경우가 많다.

Circuit Breaker 적용

하위 서비스의 장애율이 일정 수준을 넘으면 재시도를 중단한다.

이는 Retry Storm을 예방하는 가장 효과적인 방법 중 하나다.


실무에서 반드시 모니터링해야 하는 지표

재시도가 Backpressure를 증폭시키는지 확인하려면 다음 지표를 관찰해야 한다.

  • Retry Rate
  • Queue Length
  • Queue Wait Time
  • Worker Utilization
  • Thread Pool Usage
  • Connection Pool Usage
  • API Error Rate
  • Timeout Count

특히 Retry Rate와 Queue Length가 동시에 증가한다면 재시도 폭풍이 시작되고 있을 가능성이 높다.


자주 묻는 질문

Q. 재시도는 무조건 나쁜가요?

아니다.

일시적인 장애를 복구하는 데 매우 효과적이다.

문제는 재시도 자체가 아니라 과도한 재시도다.

Q. 재시도 횟수는 몇 번이 적절한가요?

서비스 특성에 따라 다르지만 일반적으로 3~5회 정도가 많이 사용된다.

중요한 것은 횟수보다 간격 설계다.

Q. Retry Storm은 어떻게 예방하나요?

지수 백오프, Jitter, Circuit Breaker, Rate Limiting을 함께 적용하는 것이 가장 효과적이다.

Q. Queue가 길어지면 재시도를 중단해야 하나요?

가능하다면 그렇다.

Queue 길이가 특정 임계치를 초과하면 재시도를 제한하거나 요청을 거부하는 것이 시스템 보호에 유리하다.


장애를 복구하는 코드가 장애를 키울 수도 있다

재시도는 분산 시스템에서 반드시 필요한 기능이다. 하지만 잘못 설계된 재시도는 장애를 복구하는 것이 아니라 장애를 증폭시키는 역할을 한다.

실제 대규모 장애 사례를 분석해보면 최초 원인보다 Retry Storm이 더 큰 피해를 만든 경우가 적지 않다. 시스템이 느려졌을 때 가장 먼저 해야 할 일은 더 많은 요청을 보내는 것이 아니라, 시스템이 회복할 시간을 주는 것이다.

결국 안정적인 시스템은 무한히 버티는 시스템이 아니라, 자신의 한계를 인지하고 적절히 속도를 조절할 수 있는 시스템이다. 재시도 역시 같은 관점에서 설계해야 한다. 적절한 재시도는 시스템을 살리지만, 과도한 재시도는 Backpressure를 가속시키며 전체 서비스를 마비시킬 수 있다.

sounghoo
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.