# RabbitMQ 叢集搭建
###### tags: `技術備忘錄` `RabbitMQ`
安裝篇->[RabbitMQ 快速安裝筆記](/DZaDoKJ8REit9tTgE_3v2Q)
入門篇->[RabbitMQ 筆記](/6X7MdpOfTEOuSFrLG0SdhQ)
---
[TOC]
---
## 相關連結
[官方Clustering Guide](https://www.rabbitmq.com/clustering.html)
[Rabbitmq叢集搭建-程式前沿](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/395960/)
## 基本設定步驟
#### vi /etc/hosts 對應設定
```bash
ip hostname
```
> **好像**需要把現有的 Nodes 全部新增上去,不然在join時會出錯。
#### 啟動叢集(每台主機)
```bash=1
rabbitmqctl stop
rabbitmq-server -detached
rabbitmqctl start_app
```
#### 叢集串接
```bash=4
rabbitmqctl stop_app
rabbitmqctl reset
#disk模式
rabbitmqctl join_cluster rabbit@hostname
#RAM模式
#rabbitmqctl join_cluster --ram rabbit@hostname
rabbitmqctl start_app
```
## Quorum Queues
***A.K.A. HA Queues***
[官方文件](https://www.rabbitmq.com/quorum-queues.html)
在cluster多節點(Nodes)的情形下才可以新增的Queue格式
![](https://i.imgur.com/21u4JFX.png)
新增時會需要先綁在其中一個Node上
如果原先綁定的Node離線,會自動將資料導到另一個Node上
![](https://i.imgur.com/b26fvPo.png)
> 旁邊的"+"代表這個Queue現在有對應到的Node數
:::warning
Quorum Queues 對應的 Node 只會包含 Queue 建立的當下有的 Node
換言之 Queue 建好後,之後再加入的 Node 就無法對應到
:::
:::danger
如果啟動中的 Node 小於 3 台
Quorum Queues 會因為 Node 過少而出錯誤
![](https://i.imgur.com/I8L7LzR.png)
所以說***啟動中 Node 必須要大於 3 台***
> 不過這個錯誤並不會導致Queue裡的資料消失
>
特殊情況:
如果 Node 為 "?",新的資料將**無法**寫進 Queue 中
:::
## 實作
### 連線
因為叢集多主機的特性,連線建立的時候如果將 HostName 寫在一般的 ConnectionFactory 裡,連線主機離線時,將無法自動重連。
如下改成 HostName List 後,即使任意節點斷線也不會影響連線。( **會自動斷線重連** )
```csharp=1
string[] hostList = { "HostName1","HostName2","HostName3","HostName4" };
var connection = factory.CreateConnection(hostList)
```
另外可以藉由這兩個 Event 監聽連線狀態
```csharp
//斷線後重新連線成功
connection.RecoverySucceeded
//斷線
connection.ConnectionShutdown
```
### 建立 Quorum Queues
```csharp
channel.QueueDeclare(
queue: "QueueName",
durable: true,
exclusive: false,
autoDelete: false,
arguments: new Dictionary<string, object>() { { "x-queue-type", "quorum" } }
);
```
如上, durable、exclusive、autoDelete 的值不可改
> BTW , QueueName 如果直接不帶( 給 **""** ),系統會自動產生 QueueName
## Consul擴展
[官方文件](https://www.rabbitmq.com/cluster-formation.html#peer-discovery-consul)
[帶有CONSUL和VAULT的RABBITMQ集群](https://piotrminkowski.com/2018/12/27/rabbitmq-cluster-with-consul-and-vault/)
```bash
rabbitmq-plugins --offline enable rabbitmq_peer_discovery_consul
```
我的 **/etc/rabbitmq/rabbitmq.conf**
```bash
loopback_users.guest = false
listeners.tcp.default = 5672
hipe_compile = false
management.listener.port = 15672
management.listener.ssl = false
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_consul
cluster_formation.consul.host = 192.168.11.191
cluster_formation.consul.svc_addr_auto = true
cluster_formation.consul.svc_addr_use_nodename = false
cluster_formation.consul.port = 8500
cluster_formation.consul.scheme = http
cluster_formation.consul.svc = rabbitmq
```
> 如果 /etc/rabbitmq 沒有 rabbitmq.conf,直接建一個就可以了
>
## Docker Iamge
## 注意事項
### /etc/hosts設定問題
根據[Rabbitmq叢集搭建-程式前沿](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/395960/)步驟,在設定 **/etc/hosts** 參數時,參考內容:
```bash
192.168.127.139 basic-server
192.168.127.140 rabbitmq-m1
192.168.127.132 rabbitmq-m2
```
其中**basic-server**,**rabbitmq-m1**,**rabbitmq-m2**,為主機名稱
不是連線叢集時的**rabbit@basic-server**
[參照錯誤](https://blog.csdn.net/yy4545/article/details/100523954)
### EPMD錯誤
如果上方/etc/hosts設定沒問題但出EPMD錯誤,執行
```bash=1
export ERL_EPMD_PORT="4369"
epmd -kill
```
[官方說明](https://www.rabbitmq.com/networking.html#epmd)