Obsidian/Recognition/Programing/RabbitMQ(AMQP)/RabbitMQ 장애조치.md

102 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

2023-08-14 16:19:25 +00:00
#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) (설정 변경 가능)
---