메시지 플랫폼 장애 에러 처리 비교 - SQS, RabbitMQ, Kafka

2022. 2. 15. 15:11ETC

메시지 플랫폼을 선택할 때, 각 제품별로 장애가 났을 때 어떻게 대처할 수 있는지 확인해봅시다.

그 전에, 해당 제품들의 기본 개념, 구조, 동작 등을 모르신다면 먼저 아래 링크에서 확인해주세요.

1. AWS SQS란? - https://yoonbing9.tistory.com/126
2. Kafka란? - https://yoonbing9.tistory.com/128
3. RabbitMQ란? - https://yoonbing9.tistory.com/129

그럼 먼저, 에러 처리의 대표적인 몇 개의 유형을 정의해봅시다.

1. 메시지 생산자

  • 메시지 유실 장애 - 상품을 주문했는데, 메시지 유실로 인해 실제 주문처리가 되지 않는다면 큰 장애라고 할 수 있습니다. 메시지 생산자는 메시지가 메시지 브로커에 제대로 저장됐는지 확인하고 메시지 브로커 저장에 실패했다면 에러 처리를 해야합니다.

2. 메시지 브로커

  • 메시지 중복 처리 장애 - 상품을 한 번 주문했는데, 같은 주문이 여러번 처리된다면 큰 장애라고 할 수 있습니다. 메시지 브로커는 똑같은 메시지가 전달 될 경우 해당 메시지의 중복을 제거하여 소비자에게 한 번의 메시지 처리를 유도할 수 있어야합니다.
  • 메시지 유실 장애 - 메시지 브로커 재기동시, 기존에 메시지 큐에 존재했던 메시지들은 모두 복구되야합니다.
  • 메시지 처리 유도 - 메시지 소비자가 메시지 처리에 실패한 경우, 해당 메시지를 처리할 다른 방법을 제공해야합니다.

3. 메시지 소비자

  • 메시지 처리 실패 - 메시지 소비자는 메시지 처리가 실패된 경우 적절한 에러 처리를 해야합니다.

이제 각 제품별로 위에서 정의한 장애가 났을 때 어떤 방식으로 에러처리를 하는지 정리해보겠습니다.

SQS

1. 메시지 생산자

  • 메시지 유실 장애 - 메시지 생산자가 SQS에 메시지를 보낼 때, 에러가 난다면, 지금까지 확인한것으로는 SQS에서 뭔가 제공해주는 매커니즘이 없습니다. 메시지 생산자가 알아서 에러 처리하여 해당 트랜잭션을 롤백할지, 재처리를 할지, 다른 곳에 저장해둘지 판단하여 적절히 처리해야합니다. (이 부분은 제가 더 알아보고 변경사항이 있을 경우 업데이트 하겠습니다)

2. 메시지 브로커

  • 메시지 중복 처리 장애 - SQS는 Standard, FIFO 두 가지 큐를 지원하는데 메시지 중복 처리 장애를 막기 위해서는 FIFO 큐를 사용해야합니다. 해당 큐는 메시지의 중복을 제거하여 한 번의 메시지 처리를 유도합니다.
  • 하지만 실제로 메시지 소비자가 메시지 처리 시간이 길어져서 ack를 브로커에 전달하지 못하면 SQS는 해당 메시지를 다른 메시지 소비자에게 전달하여 메시지 중복 처리가 가능하게 됩니다. 따라서 메시지 중복 처리는 메시지 소비자가 책임을 지던가, 애초에 메시지가 중복 처리되지 않게 어플리케이션을 잘 설계해야합니다.메시지 유실 장애 - SQS는 메시지를 내부적으로 여러 가용영역에 걸쳐 저장하게 됩니다. 개발자는 이를 신뢰하고 비즈니스 로직에 집중하면 됩니다.

여러 서버에 저장

  • 메시지 처리 유도 - 메시지를 가져간 소비자가 메시지 처리를 할 수 없는 경우, SQS는 다른 소비자에게 해당 메시지를 전달하여 처리하도록 유도합니다. 설정된 값만큼 소비자가 메시지를 가져갈 수 있으며, 해당 값만큼 가져갔지만 소비자에게 ack가 오지 않는 경우 SQS는 해당 메시지를 DLQ(Dead Letter Queue)에 모아두어 후처리를 유도합니다.

3. 메시지 소비자

  • 메시지 처리 실패 - 메시지 소비자가 메시지를 정상 처리할 경우 메시지 브로커에게 ack를 전달하여 해당 메시지 삭제를 요청합니다. 하지만 메시지 처리에 실패한 경우, ack를 보내지 않음으로서 메시지 처리 실패를 간접적으로 브로커에게 알려서 에러 처리를 브로커에게 위임할 수 있습니다. 혹은 정상 처리하여 ack를 보내고 해당 메시지 소비자가 따로 에러 처리를 진행하는 방법도 있습니다.

RabbitMQ

1. 메시지 생산자

  • 메시지 유실 장애 - SQS와 마찬가지로 메시지를 보낼때 에러가 난다면 메시지 생산자쪽에서 에러 처리를 해줘야합니다. RabbitMQ는 Kafka와 자주 비교되고는 하는데, Kafka처럼 프로듀서 ack 옵션으로 얼마나 더 안전하게 저장할 것인지에 대한 매커니즘은 제공하지 않지만 publisher confirms을 사용하면 생산자가 브러커에 메시지가 잘 저장됐는지 비동기로 응답받을 수 있습니다.
    https://blog.rabbitmq.com/posts/2011/02/introducing-publisher-confirms/
 

Introducing Publisher Confirms | RabbitMQ - Blog

Introducing Publisher Confirms February 10, 2011 In many messaging scenarios, you must not lose messages.  Since AMQP gives few guarantees regarding message persistence/handling, the traditional way to do this is with transactions, which can be unaccepta

blog.rabbitmq.com

2. 메시지 브로커

  • 메시지 중복 처리 장애 - RabbitMQ는 SQS FIFO 큐처럼 중복을 큐 내에서 자체적으로 처리하는 기능이 없습니다. 만약에 큐에서 메시지 중복 처리를 하려면 관련 플러그인을 적용하는 방법이 있습니다.
    https://github.com/noxdafox/rabbitmq-message-deduplication
 

GitHub - noxdafox/rabbitmq-message-deduplication: RabbitMQ Plugin for filtering message duplicates

RabbitMQ Plugin for filtering message duplicates. Contribute to noxdafox/rabbitmq-message-deduplication development by creating an account on GitHub.

github.com

 

DLX 처리 과정

  • 메시지 유실 장애(메시지 소비자 문제) - 메시지를 소비자가 가져가게 되면, 소비자가 ack를 보내기 전에는 메시지를 삭제하지 않습니다. 만약 ack가 일정 시간(TTL)동안 오지 않는다면 해당 메시지는 DLX(Dead Letter Exchange) 과정을 거치게 됩니다.
    DLX는 실패처리된 메시지들이 DLX라고 지정된 Exchange로 이동하는 것입니다. 이렇게 이동된 메시지는 적절하게 에러 처리를 하게 됩니다.
    위 사진의 예시의 경우 해당 메시지는 다시 작업 큐로 들어가서 재처리를 하게 됩니다. 만약 재처리 횟수가 임계값에 도달하면 SQS의 DLQ 처럼 실패된 메시지만 모아두는 특정 큐에 해당 메시지를 이동하여 후처리를 유도할 수도 있습니다.
  • 메시지 유실 장애(메시지 브로커 문제) - 메시지 소비자에 문제가 생겼을 때 메시지 유실은 막을 수 있지만, 여전히 메시지 브로커가 재기동됐을 때 메시지 유실 가능성이 있습니다. 이를 방지하기 위해 RabbitMQ는 메시지가 큐에 저장될 때 file에도 저장되게 하는 Message durability 을 지원합니다. 하지만 file을 쓰는 도중에 서버가 죽는다면 메시지를 복구할 수 없습니다. 그래서 RabbitMQ는 메시지 유실을 최소화하는 여러가지 매커니즘을 제공합니다

https://m.blog.naver.com/PostView.naver?blogId=tmondev&logNo=221051503100&navType=by 

 

RabbitMQ로 메시지 손실 최소화 하는 법(1)

우리는 메시지를 발생한 후 받아서 처리하는 메시징 시스템의 도입이 필요했다. 물론 저장소를 이용하여 직...

blog.naver.com

  • 메시지 처리 유도 - SQS는 메시지 소비자가 메시지를 처리할 수 없는 경우 다른 메시지 소비자에게 해당 메시지를 전달하여 처리하도록 할 수 있었습니다. 하지만 RabbitMQ는 처리되지 못하는 메시지는 바로 DLX과정을 거쳐 에러 처리를 하게 됩니다. 에러 처리에서 재처리를 진행할 경우, 해당 메시지는 여러 소비자들에게 라운드 로빈 방식으로 메시지가 전달 될 것입니다. SQS는 재처리 후 DLQ로 이동하는 반면, RabbitMQ는 DLX 후 재처리를 할 수 있기 때문에 순서가 다르다고 생각하면 될 것 같습니다.

3. 메시지 소비자

  • 메시지 처리 실패 - SQS와 마찬가지로 소비자가 메시지 처리에 실패한 경우 ack를 보내지 않거나, nack를 보내서 메시지 처리에 실패했다고 브로커에 알려 에러 처리를 위임할 수 있습니다.

Kafka

1. 메시지 생산자

  • 메시지 유실 장애 - 메시지를 보낼 때 에러가 난다면 생산자에서 에러 처리를 해야합니다. 그 밖에 카프카는 메시지가 잘 전달된 후에 메시지가 잘 저장됐는지 ack 옵션으로 응답받을 수 있습니다.
    ack = 0 - 생산자는 메시지가 저장됐는지 확인하지 않습니다.
    ack = 1 - 메시지가 리더 파티션에 저장됐는지 확인합니다.
    ack = ALL - 메시지가 리더 파티션과 팔로워 파티션 모두 저장됐는지 확인합니다.
    ack = ALL, min.insync.replicas - 몇 개의 파티션에 저장된 후에 응답받을지 설정
    이렇게 카프카는 메시지 생산자가 브로커에 메시지가 잘 저장됐는지에 대한 신뢰성을 보장받을 수 있습니다.
  • 메시지 중복 처리 장애 - SQS와 다르게 카프카는 메시지 중복 처리 옵션을 메시지 생산자에서 지원합니다. 바로 멱등성 프로듀서입니다. 멱등성 프로듀서는 enable.idempotence 옵션을 제공하며 기본값은 false이고 이는 중복 제거를 하지 않는 것입니다. true로 설정하여 중복제거를 설정할 수 있습니다.

2. 메시지 브로커

  • 메시지 유실 장애 - 카프카는 여러 브로커로 클러스터를 형성하여 운영됩니다. 따라서 SQS와 같이 메시지가 카프카에 전달되면 해당 메시지는 여러 서버에 중복 저장하여 유실 가능성을 최소화합니다. 
    컨트롤러가 아닌 브로커에 장애가 생길 경우, 컨트롤러는 다른 브로커들의 상태를 체크하여 장애가난 브로커에 리더 파티션이 존재하는 경우, 다른 브로커에서 리더 파티션을 재선출합니다.
    컨트롤러 브로커가 장애가 난 경우, 주키퍼 설정에 따라 컨트롤러 브로커가 재선출됩니다.
  • 메시지 처리 유도 - 클러스터의 브로커 중에 하나는 코디네이터 역할을 하게 됩니다. 만약 컨슈머 그룹의 하나의 컨슈머가 장애가 났을 경우, 코디네이터는 해당 컨슈머에 연결된 파티션이 다른 정상적으로 작동하는 컨슈머에게 연결되도록 재분배합니다.

3. 메시지 소비자

  • 메시지 처리 실패 - 다른 메시지 브로커와는 다르게 카프카는 ack를 보내 메시지가 삭제되도록 하지 않습니다. 따라서 에러 처리를 브로커에 위임하지 않고 메시지 소비자가 직접 에러 처리를 담당해야합니다. 

카프카 장애 처리는 밑의 블로그를 참조하였습니다.

https://velog.io/@jwpark06/%EC%9E%A5%EC%95%A0%EC%97%90-%EB%8C%80%EC%9D%91%ED%95%98%EB%8A%94-Kafka

 

장애에 대응하는 Kafka

여러 종류의 장애에 대응하는 카프카.. 레코드의 장애 대처 파티션의 장애 대처 브로커의 장애 대처 일반적으로 클러스터의 다수 브로커 중 한 대의 브로커는 컨트롤러의 역할을 하게 된다. 클

velog.io

 

'ETC' 카테고리의 다른 글

메시징 플랫폼 비교 - SQS, SNS, Kafka, RabbitMQ  (2) 2022.02.11
RabbitMQ란?  (0) 2022.02.09
Kafka(카프카)란?  (0) 2022.02.07
AWS SNS란?  (0) 2022.02.07
AWS SQS란?  (0) 2022.02.07