---
# System prepended metadata

title: RabbitMQ 叢集搭建
tags: [RabbitMQ, 技術備忘錄]

---

# 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)

