래빗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...

클러스터링 - CAP 와 PACELC

CAP 와 PACELC http://happinessoncode.com/2017/07/29/cap-theorem-and-pacelc-theorem/

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

클러스터링과 네트워크 파티션 클러스터링을 사용해서 복제를 통한 데이터 안정성, 작업 가용성, 처리량 향상 등 여러 목표를 달성할 수 있다. 클러스터 멤버간의 네트워크 연결 실패는 데이터 일관성 및 가용성에 영향을 준다. 각각의 어플리케이션은 일관성에 대한 요구사항이 다르고, 다른 규모의 비가용성을 견디므로 다른 '파티션 처리전략'을 사용할 수 있다. 1. 네트워크 파티션 감지 노드는 다른 노드가 일정시간동안(디폴트 60초) 노드에 접속할 수 없으면 해당 노드가 작동 중지되었다고 판단한다. 두 노드가 다시 접촉하면, 두 노드가 서로 장애가 발생했다고 생각하면 노드는 파티션이 발생했는지 결정한다. 이것은 다음과 같은 형식으로 래빗MQ 로그에 기록된다. 파티션 존재여부는 서버로그, HTTP API(모니터링용) 및 CLI 명령인 rabbitmqctl cluster_status 을 통해 식별할 수 있다. rabbitmqctl cluster_status 는 보통 partition에 대한 빈 리스트를 보여주지만, 네트워크 파티션이 발생하면 그곳에 나타난다. HTTP API는 각 노드에 대한 파티션 정보를 반환한다. 관리UI는 파티션이 발생한 경우 개요 페이지에 경고를 표시한다. ex) 래빗MQ 로그 =ERROR REPORT==== 15-Oct-2012::18:02:30 === Mnesia(rabbit@hostname): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, hare@hostname} ex) rabbitmqctl cluster_status # => Cluster status of node rabbit@smacmullen ... # => [{nodes,[{disc,[hare@smacmullen,rabbit@smacmullen]}]}, # =>  {running_nodes,[rabbit@smacm...

래빗MQ 메시지 발행 성능절충

1. 래빗MQ에는 메시지 발행에 대한 여러 설정이 있다. 메시지 발행속도는 배달 보장 메커니즘을 사용하면 느려진다. 추가적인 배달 보장없이 메시지를 발행하면 속도는 훨씬 빠르지만 안전하지 못하다. 아래와 같은 설정들을 할수 있다. - 배달보장 없음   : 걍 빠르다. - 실패통보   : 메시지의 mandatory 플래그를 true로 전달.    래빗MQ는 라우팅 못하면 basic.return RPC를 통해 메시지를 발행자에게 다시 보냄.    (성공하면 안보냄)    basic.return은 비동기로 동작하고, 처리하도록 설정해야 한다.    보통 콜백 메소드 등록해야 할 것이다. - 발행자 확인   : 래빗MQ는 basic.ack(성공) or basic.nack(실패)를 리턴한다.     보통 비동기적으로 응답하는 콜백 핸들러를 전달해야 한다. - 대체 익스체인지   : 라우팅할 수 없으는 메시지를 dead letter queue에 저장.     익스체인지 선언시 대체 익스체인지 명시. - 트랜잭션   : 메시지 전달 보장하는 방법 (발행자 확인 구현전에는 이게 유일한 방법이었다고 함)     브로커의 큐에 메시지를 성공적으로 전달했음을 basic.return으로 응답.     tx.select, tx.selectok, tx.commitok, tx.rollback 이런 것들이 사용된다.     (걍 발행자 확인을 쓰는 것이 권장된다.) - HA 큐   : 큐에 있는 동안 손실되지 않도록 하는 것.     큐를 여러서버에 중복해 복사본을 저장하는 기능     HA 큐로 메시지가 발행되면 HA 큐를 담당하는 클러스터의 각 서버로 메시지 동기화.  ...

래빗MQ 메시지 속성

1. 래빗MQ 메시지는 AMQP 스펙의 세가지 low-level 프레임으로 구성된다. - 메소드 프레임 - 콘텐츠 헤더 프레임 - 바디 프레임 2. 콘텐츠 헤더 프레임은 Basic.Properties 데이터 구조로 사전에 정의한 값들이 있다. - content-type : 소비자에게 메시지 본문을 해석하는 방법을 전달   ex) application/json, application/xml - content-encoding : 메시지 본문이 어떤 방법으로 압축 or 인코딩 되었는지 전달   ex) base64, gzip - message-id, correlation-id : 메시지, 메시지 응답 고유하게 식별   ex) uuid   : 어플리케이션에서 원하는 용도로 자유롭게 사용     correlation-id에는 message-id의 값을 지정할 수 있다. - timestamp : 메시지 크기를 줄이고 메시지 생성 시점에 대한 표준 시간 전달   : 이것도 어플레키에션 용도     메시지 성능 측정 가능. 메시지 수명 체크후 처리여부 결정 가능 - expiration : 메시지의 만료   : 문자열, 만료됐으면 큐에 안들어가고 삭제. 큐설정으로도 만료가능(x-message-ttl) - delivery-mode : 메시지를 디스크 또는 메모리에 저장할지 - app-id, user-id : 문제가 발생한 발행자 어플리케이션 추적 - reply-to : 패턴을 값으로 전달해 응답 메시지를 라우팅 - headers : 메시지 라우팅할때 사용자 정의 형식의 속성 정의 - priority : 메시지 우선순위 0~9(0이 높음) -  cluster-id  : (사용을 권장하지 않음) - type : 발행자와 소비자 사이의 계약을 정의 출처 : rabbitmq in depth 3장 (도서) ...

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

1. 클러스터 래빗MQ 클러스터는 둘 이상의 서버를 하나의 래빗MQ처럼 사용할 수 있게 한다. 익스체인지, 큐, 바인딩, 사용자, 가상호스트, 정책 등의 런타임 상태가 모든 노드에서 공유된다. 장애허용(fault tolerance) 시스템을 구성하려는 경우, HA큐를 사용한다. HA큐는 여러 클러스터 노드에 걸쳐있고, 메시지와 큐 상태를 공유한다. HA 큐의 노드 중 하나가 다운돼도 다른 노드들에는 메시지와 큐 상태가 계속 유지된다. 클러스터는 대기시간이 짧은 LAN에서만 구성 가능하다. 아마존 EC2와 같은 클라우드 환경에서도 가능하지만 가용성 영역(availability zone)에 걸쳐서는 안된다. 대기시간이 긴 WAN이나 인터넷 연결에서는 Shovel과 Federation를 써야 함. 클러스터 공유 상태를 관리하는 작업의 로드는 노드 수에 비례한다. 2. 노드유형 디스크 노드 or RAM 노드. - 디스크 노드는 클러스터의 런타임 상태를 RAM과 디스크에 저장. - RAM 노드는 메모리 데이터베이스에만 저장. (익스체인지, 큐, 바인딩, 가상호스트, 사용자, 정책) 노드유형은 메시지의 디스크 저장과는 관련없다. 메시지를 디스크 저장하려면 메시지 속성 delivery-mode를 2(persistent)로 설정. 장애 발생후 재접속 할 때, - 디스크 노드는 런타임상태 재구성 - RAM 노드는 런타임 상태를 포함하지 않는다. 클러스터를 생성할 때 최소 하나의 디스크노드가 있어야 한다. 3. 동작 클러스터에 발행한 메시지는 큐가 클러스터의 어느 노드에 있는지와 상관없이 올바르게 전달된다. HA큐를 사용하면 성능이 저하될 수 있다. 큐에 메시지를 저장하거나 큐에서 메시지를 사용할 때, HA큐가 있는 모든 노드로 알려줘야 하니까. 4. 노드 추가 방법 rabbitmq.config 환경 파일을 편집하여 클러스터의 각 노드를 정의(이걸 써야함) 또는 rabbitmqctl 명령을 사용해 클러스터에 노드...

래빗MQ에서 사용하는 프로토콜인 AMQP의 컨셉

1. AMQP 0-9-1은? Advanced Message Queuing Protocol 클라이언트 어플리케이션을 메시징 미들웨어 브로커와 통신할 수 있도록 하는 메시징 프로토콜 메시징 브로커는 퍼블리셔(프로듀서라고도 함)로부터 메시지를 받아서 컨슈머로(처리하는 어플리케이션) 라우팅한다. 네트워크 프로토콜이므로 퍼블리셔와 컨슈머, 브로커는 다른 머신에 있어도 된다. 2. AMQP 0-9-1 모델 요약 메시지는 exchange에 퍼블리시된다. exchange는 우체국, 우체통에 비교된다. exchange는 binding이라는 규칙을 사용하여 메시지를 복사하여 큐로 분배한다. AMQP 브로커는 메시지를 큐를 구독한 컨슈머로 전달하거나, 필요시 컨슈머가 큐에서 메시지를 가져온다. 메시지를 퍼블리시할때, 퍼블리셔는 다양한 메시지 속성을 지정할 수 있다.(메시지 메타-데이터) 이 메타-데이터의 일부는 브로커에 의해 쓰일 수 있다. 그러나 나머지는 완전히 브로커에게는 불투명하고 메시지를 받는 어플리케이션에 의해서만 쓰인다. 네트워크는 불안정적이고 어플리케이션은 프로세스에 실패할 수 있다. 그래서 AMQP에는 메시지 확인(message acknowledgements) 개념이 있다. 메시지가 컨슈머로 전달될 때, 컨슈머는 자동적으로, 또는 개발자가 선택한 때 바로 브로커에게 알린다. 브로커는 메시지에 대한 알림을 받으면 메시지(또는 메시지 그룹)를 큐에서 완전히 지운다. 특정 상황에서, 메시지가 라우팅되지 못했을때, 메시지는 퍼블리셔에게 되돌아가거나, 드랍되거나, 만약 브로커가 extension을 구현했으면 '죽은 편지 큐'로 이동된다. 퍼블리셔는 특정 파라미터를 사용하여 퍼블리시 해서 어떻게 상황들을 처리할지 선택한다. 3. queue, exchange, binding을 집합적으로 AMQP 엔티티라고 한다. exchange는 메시지가 전송되는 AMQP 엔티티이다. exchange는 메시지를 가져와서 0개 이상의...