#RabbitMQ ## 장애 방지 방법 ### 1. 브로커 #### 1-1. Clustering > rabbitmqctl의 join_cluster 명령을 통해서 클러스터를 구성할 수 있다. [공식문서](https://www.rabbitmq.com/clustering.html) - 주의할점 - 모든 노드는 같은 Erlang 쿠키 정보를 가지고 있어야 한다. - 네트워크는 LAN을 통해서 구성돼야 한다. - 모든 노드는 같은 버전의 RabbitMQ와 Erlang으로 작동 되어야 한다. - 클러스터에 참여하기 전 노드는 DISK or RAM 모드를 설정할 수가 있다. (RAM 모드 설정 시 메시지 손실을 방지할 수 없기 때문에 DISK 모드를 권장한다) #### 1-2. Exchange and Queue Durability >서버의 오류로 인해서 재가동 시 이전의 설정으로 자동 복원이 되도록 한다. > 아래의 함수를 통해 Exchanger, Queue Durability를 설정하여 브로커가 재가동 시에도 이전의 정보를 가지고 복원되게 할 수 있다. durable 값을 true로 넘겨준다. ``` Erlang Channel.exchangeDeclare(exchange_name, exchange_type, durable, auto_delete, args); Channel.queueDeclare(queue_name, durable, exclusive, autoDelete, args); ``` #### 1-3. Queue Mirroring > 큐 미러링을 통해서 모든 노드에 메시지를 동기화 시킨다. > > 동일 클러스터에 있는 노드중 하나의 노드가 동작하지 않는다면 큐에 있는 메시지는 노드가 다시 동작하지 않는 한 복구되지 않는다.(모든 노드의 큐는 동일한 메시지를 가지지 않는다.) > 큐 미러링을 통해서 이러한 점을 보완할 수 있다. > > **큐 미러링 설정** > rabbitmqctl set_policy 명령을 통해서 미러링 정책을 정할 수 있다. ex) rabbitmqctl set_policy -p {호스트명} {정책명} {큐이름(정규식표현가능)} {정책파라미터} ※ 모든 노드의 큐에 미러링을 설정하게 된다면 메시지 신뢰성은 높아지겠지만 성능은 저하될 수 있다. ###### 큐미러링 설정 예) ``` Erlang # 1. host1에 ha-all라는 정책 이름을 가지고 ‘ha.’ 이름으로 시작하는 큐를 모든 노드에 미러링 rabbitmqctl set_policy -p host1 ha-all “^ha\.” ‘{“ha-mode”:”all”}’ # 2. host1에 ha-two라는 정책 이름을 가지고 ‘two.’ 이름으로 시작하는 큐를 2개의 노드에만 미러링 rabbitmqctl set_policy -p host1 ha-two “^two\.” ‘{“ha-mode”:”exactly”,”ha-params”:2}’ # 3. host1에 ha-nodes라는 정책 이름을 가지고 ‘nodes.’ 이름으로 시작하는 큐를 특정 노드에 미러링 rabbitmqctl set_policy -p host1 ha-nodes “^nodes\.” ‘{“ha-mode”:”nodes”, “ha-params”:[“rabbit@jun-VirtualBox”]}; ``` #### 1-4. Master and Slave > 큐의 마스터와 슬레이브에 대해서 고려하여 서버를 구성한다. > > - 큐에는 마스터와 슬레이브 두가지 타입이 있다. > - 모든 노드에 존재하는 각 큐에는 반드시 하나의 마스터 큐가 있어야 한다. > - 큐에 메시지가 라우팅 되면 가장 먼저 마스터 큐에 메시지가 들어오게 되고 이 후 슬레이브 큐에 전달된다. ###### 장애시 마스터 자동 지정 우선순위 1. 메시지 동기화 타입인 노드 2. 디스크타입으로 동작하는 노드 3. 조인순서가 빠른 노드 ##### 참고 https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=oidoman&logNo=220833403583 (RabbitMQ ACK) https://ssup2.github.io/theory_analysis/RabbitMQ_Ack/ --- ### Queue Durable 설정 >재기동시 메시지 유지 [참고](https://skarlsla.tistory.com/14), Storage저장방식, RabbitMQ서버 장애 대응 - queue생성시 durable속성을 true로 주고 만든다. - message publish할때 MessageProperties.PERSISTENT_TEXT_PLAIN을 설정함 - publisher confirms 사용 ### RabbitMQ ACK > Producer와 Consumer 사이의 Message 전달을 보장 #### Producer Confirm - Producer -> RabbitMQ 메시지 전달 - RabbitMQ -> Producer ACK 전송. - Exchange에 설정된 규칙에 따라서 수신한 Message를 버려지면 Producer에게 즉시 ACK전송. - Message가 Queue로 전송되면 Queue가 Message를 저장한 이후에 Producer에게 ACK 전송. - Queue가 Mirroring 되어 있다면 Message는 Mirroring된 모든 Queue에 복사된 이후에 Producer에게 ACK 전송. - 만약 ACK가 일시작 Network장애로 인해서 Producer에게 전달되지 않은 상황인경우 연결이 재생성된 이후에 ACK를 받지 못한 Message를 재전송함. ※ 이경우 RabbitMQ는 중복된 Message를 수신할 수 있고 Consumer에게 그대로 전송됨. #### Consumer Acknowledgement - RabbitMQ -> Consumer Message 전달 - Consumer -> RabbitMQ ACK 전송. (Message 처리후) - RabbitMQ Queue 메시지 삭제 - Consumer는 Message를 수신한 다음 반드시 특정 시간내에 ACK를 전송할 필요 없음(Time Out 없음, 수동Ack처리 가능) - RabbitMQ에서 ACK를 받지못한상태에서 연결끊어지면 연결 재생성이후 Message 재전송. - Message가 정상 수신되었어도 Consumer에 의해 Reject(해당 Msg), Nack(ACK를 전송하지 않은 모든 Msg) 될 수 있음. - 거절된 Message는 Reject/Nack응답과 함께 전동된 Requeue옵션에 따라 처리가 달라짐. - Requeue옵션 설정 O : Message는 원래 있던 Queue로 돌아간다. (이후 Consumer로 재전송) - Requeue옵션 설정 X : Queue의 DLX(Dead Letter Exchange)옵션에 따라 처리 - DLX 옵션 O : DLX로 전송. - DLX 옵션 X : 버려짐. - RabbitMQ Server가 데이터를 계속 가지고 있다면, RabbitMQ Server는 Delivery Acknowledgement Timeout(Default : 30초) 시간 동안 보관 하고 이후 데이터를 ACK 받은 것으로 처리 한다. [참고](https://kaizen8501.tistory.com/220) (설정 변경 가능) ---