래빗MQ 메시지 딜리버리 확인 메커니즘 - 소비자에서 브로커로

소비자 acknowledgements, 발행자 confirms

프로토콜 메소드는 성공적으로 진행되었는지 보장되지 않기 때문에,
발행자와 소비자는 딜리버리와 처리 확인을 위한 메커니즘이 필요하다.
래빗MQ가 지원하는 몇몇 메시징 프로토콜은 이러한 특성을 제공한다.

소비자로부터의 딜리버리 처리 acknowledgements는 AMQP 0-9-1 용어로 알려져 있다.(소비자 -> 브로커)
발행자로 가는 브로커 acknowledgements는 발행자 확인이라고 부르는 프로토콜 확장이다.(브로커 -> 발행자)

두개의 특성은 같은 아이디어로부터 나왔고, TCP로부터 영감을 받았다.
이것들은 퍼블리시에서 래빗MQ노드로, 래빗MQ노드에서 소비자로의 reliable한 딜리버리를 위해 필수적이다.

1.
(consumer) delivery acknowledgements
래빗MQ가 소비자로 메시지를 보낼때, 언제를 메시지가 성공적으로 보내졌는지로 할지 알 필요가 있다.
이런 로직은 시스템에 따라 다르다. 그러니까 어플리케이션에서 결정하는게 우선적이다.
AMQP 0-9-1에서는 소비자가 basic.consume 메소드를 사용하여 등록하거나 메시지가 basic.get 메소드로 fetch되었을때로 한다.

2.
딜리버리 구분자 : delivery tags
다른 주제를 보기 앞서, 어떻게 딜리버리가 구분되는지 설명하는것이 중요하다.(그리고 acknowledgements는 각자의 딜리버리이다.)
소비자가 등록되었을때, 메시지는 basic.deliver 메소드를 사용해서 래빗MQ에 의해서 전달된다.(푸쉬된다.)
이 메소드는 채널 상에서 딜리버리를 유일하게 구분하는 delivery tag를 가지고 온다. 그러니까 딜러버리의 scope은 채널이다.

3.
딜러버리 태그는 단조롭게 증가하는 양의 정수이고, 클라이언트 라이브러리와 같은 것에 의해서 표시된다.
딜리버리를 확인(acknowledge)하는 클라이언트 라이브러리 메소드는 delivery tag를 인자로 배달한다.
딜러버리 태그는 채널이 범위이기 때문에, 딜리버리는 수신한 같은 채널에서 확인되어야 한다.
다른 채널에서의 확인은 unknown delivery tag 프로토콜 exception이 나고, 채널이 닫힌다.

4.
소비자 acknowledgement 모드와 데이터 안정성 고려
노드가 메시지를 컨슈머로 딜리버리할때, 메시지가 컨슈머에 의해 처리되어야 하는지 (또는 적어도 수신되었는지) 결정해야 한다.
여러가지로 실패할 수 있기 때문에(클라이언트 연결, 컨슈머 앱, 등), 이 결정은 데이터 안정성의 고려사항이다.
메시징 프로토콜은 보통 확인 메커니즘을 제공하는데, 이는 컨슈머에게 딜리버리를 그들이 연결된 노드로 확인하도록 허용한다.
메커니즘이 사용되는지 여부는 소비자가 subscribes할때 결정된다.

acknowledgement모드가 사용되는지 여부에 따라서, 래빗MQ는 메시지가 보내진 직후, 또는 명시적으로("manual") 클라이언트 acknowledgement가 수신되고나서
성공적으로 메시지 딜리버리가 되었다고 생각할 수 있다.

basic.ack은 잘 전달되었다는 acknowledgement이다.
basic.nack은 반대이다.
basic.reject도 반대이지만, basic.nack과 비교하여 한가지 제한사항이 있다.

어떻게 이 메소드들이 클라이언트 라이브러리 API들에서 나타나는지 보자.
잘 전달되었다는 acknowledgement는 전달되었고 폐기되도록 기록한다.
basic.reject의 부정적인 acknowledgement는 같은 효과이다. 다른점은 의미적으로 다르다.

automatic acknowledgement 모드에서는, 메시지가 전달되지마자 성공적으로 딜리버리되었다고 간주된다.
이 모드는 감소된 딜리버리 안정성과 컨슈머 처리를 높은 처리량과(consumer가 감당할 수 있다면) trade-off한다.
이 모드는 종종 fire-and-forget으로 불린다.
manual acknowledgement 모델과 다르게, 딜리버리가 성공되기 전에 소비자의 TCP연결이나 또는 채널이 닫히면
전송된 메시지가 손실된다. 그러므로 automatic message acknowledgement는 안전하지 않게 생각되어야 하고, 모든 workload에는 적합하지 않다.

automatic acknowledgement 모드에서 고려되어야 하는 중요한 것은 소비자 부하이다.
manual acknowledgement 모드는 보통 채널에서 진행중인 딜리버리의 수를 제한하는 바운딩된 채널 prefetch와 함께 쓰인다.
그러나 automatic에서는 이러한 제한이 없다. 컨슈머는 전송율에 의해 압도되어질수 있다.
메모리가 폭발하여 OS에서 의해 종료될 수가 있다.
그러니 automatic모드는 오직 딜리버리를 효율적이고 일정한 rate로 처리할 수 있는 컨슈머에게 추천된다.

5.
긍정적으로 acknowledging deliveries
딜리버리 acknowledgement를 위해 사용되는 API 메소드는 대개 클라이언트 라이브러리에서 채널에서의 작업으로 표시된다.


출처: https://www.rabbitmq.com/confirms.html

댓글

이 블로그의 인기 게시물

래빗MQ 클러스터링 - 2. 네트워크 파티션

래빗MQ 클러스터링 - 1. 클러스터링