中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

RabbitMQ集群高可用原理及實戰部署是怎樣的

發布時間:2021-12-03 19:34:49 來源:億速云 閱讀:192 作者:柒染 欄目:大數據

這篇文章將為大家詳細講解有關RabbitMQ集群高可用原理及實戰部署是怎樣的,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

今天我們一起來聊聊關于 RabbitMQ 集群原理和部署流程

一、介紹

在前幾篇文章中,我們詳細的介紹了 RabbitMQ 的內部結構和使用,以及 SpringBoot 和 RabbitMQ 整合,都是基于單臺 RabbitMQ 進行使用的。

我們知道在微服務流行的當下,一旦單臺服務器掛了,基本上就無法提供高可用的服務了,因此為了保證服務高可用,在生產環境上我們通常的做法是搭建一個 RabbitMQ 集群,即使某臺 RabbitMQ 故障了,其他正常的 RabbitMQ 服務器依然可以使用,應用程序的持續運行不會受到影響。

 

二、集群架構原理

在前幾篇文章中,我們有介紹到 RabbitMQ 內部有各種基礎構件,包括隊列、交換器、綁定、虛擬主機等,他們組成了 AMQP 協議消息通信的基礎,而這些構件以元數據的形式存在,它始終記錄在 RabbitMQ 內部,它們分別是:

  • 隊列元數據:隊列名稱和它們的屬性
  • 交換器元數據:交換器名稱、類型和屬性
  • 綁定元數據:一張簡單的表格展示了如何將消息路由到隊列
  • vhost 元數據:為 vhost 內的隊列、交換器和綁定提供命名空間和安全屬性

這些元數據,其實本質是一張查詢表,里面包括了交換器名稱和一個隊列的綁定列表,當你將消息發布到交換器中,實際上是將你所在的信道將消息上的路由鍵與交換器的綁定列表進行匹配,然后將消息路由出去。

RabbitMQ集群高可用原理及實戰部署是怎樣的
消息路由表

有了這個機制,那么在所有節點上傳遞交換器消息將簡單很多,而 RabbitMQ 所做的事情就是把交換器元數據拷貝到所有節點上,因此每個節點上的每條信道都可以訪問完整的交換器。

RabbitMQ集群高可用原理及實戰部署是怎樣的  

如果消息生產者所連接的是節點 2 或者節點 3,此時隊列1的完整數據不在該兩個節點上,那么在發送消息過程中這兩個節點主要起了一個路由轉發作用,根據這兩個節點上的元數據轉發至節點1上,最終發送的消息還是會存儲至節點1的隊列1上。

同樣,如果消息消費者所連接的節點2或者節點3,那這兩個節點也會作為路由節點起到轉發作用,將會從節點1的隊列1中拉取消息進行消費。

與常見的集群主從架構模式不同的地方在于RabbitMQ 集群模式下,僅僅只是同步元數據,每個隊列內容還是在自己的服務器節點上

這么設計主要還是基于集群本身的性能和存儲空間上來考慮:

  • 存儲空間:真正存放數據的地方是在隊列里面,如果每個集群節點都擁有所有隊列的完全數據拷貝,那么每個節點的存儲空間會非常大,集群的消息積壓能力會非常弱。例如你現在存儲了 3G 隊列內容,那么在另外一個只有 1G 存儲空間的節點上,就會造成內存空間不足的情況,也就是無法通過集群節點的擴容提高消息積壓能力。
  • 性能:消息的發布者需要將消息復制到每一個集群節點,每一條消息都會觸發磁盤活動,這會導致整個集群內性能負載急劇拉升。

既然每個隊列內容還是在自己的服務器節點上,同樣也會帶來新的問題,那就是如果隊列所在服務器掛了,那存在服務器上的隊列數據是不是全部都丟失了

在單個節點上,RabbitMQ 存儲數據有兩種方案:

  • 內存模式:這種模式會將數據存儲在內存當中,如果服務器突然宕機重啟之后,那么附加在該節點上的隊列和其關聯的綁定都會丟失,并且消費者可以重新連接集群并重新創建隊列;
  • 磁盤模式:這種模式會將數據存儲磁盤當中,如果服務器突然宕機重啟,數據會自動恢復,該隊列又可以進行傳輸數據了,并且在恢復故障磁盤節點之前,不能在其它節點上讓消費者重新連到集群并重新創建隊列,如果消費者繼續在其它節點上聲明該隊列,會得到一個 404 NOT_FOUND 錯誤,這樣確保了當故障節點恢復后加入集群,該節點上的隊列消息不會丟失,也避免了隊列會在一個節點以上出現冗余的問題。

在集群中的每個節點,要么是內存節點,要么是磁盤節點,如果是內存節點,會將所有的元數據信息僅存儲到內存中,而磁盤節點則不僅會將所有元數據存儲到內存上, 還會將其持久化到磁盤

在單節點 RabbitMQ 上,僅允許該節點是磁盤節點,這樣確保了節點發生故障或重啟節點之后,所有關于系統的配置與元數據信息都會從磁盤上恢復。

而在 RabbitMQ 集群上,至少有一個磁盤節點,也就是在集群環境中需要添加 2 臺及以上的磁盤節點,這樣其中一臺發生故障了,集群仍然可以保持運行。其它節點均設置為內存節點,這樣會讓隊列和交換器聲明之類的操作會更加快速,元數據同步也會更加高效。

 

三、集群部署

為了和生產環境保持一致,我們選用CentOS7操作系統進行環境部署,分別創建 3 臺虛擬機。

# 3臺服務器的IP
197.168.24.206
197.168.24.233
197.168.24.234
 

放開防火墻限制,保證 3 臺服務器網絡都可以互通!

 
3.1、重新設置主機名

由于 RabbitMQ 集群連接是通過主機名來連接服務的,必須保證各個主機名之間可以 ping 通,重新設置 3 臺服務器主機名,所以需要做以下操作:

# 修改節點1的主機名
hostname node1

# 修改節點2的主機名
hostname node2

# 修改節點3的主機名
hostname node3
 

編輯/etc/hosts文件,添加到在三臺機器的/etc/hosts中以下內容:

sudo vim /etc/hosts
 

添加內容如下:

197.168.24.206 node1
197.168.24.233 node2
197.168.24.234 node3
     
3.2、rabbitMQ安裝

RabbitMQ 基于 erlang 進行通信,相比其它的軟件,安裝有些麻煩,不過本例采用rpm方式安裝,任何新手都可以完成安裝,過程如下!

 
3.2.1、安裝前命令準備

輸入如下命令,完成安裝前的環境準備。

yum install lsof  build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz wget vim
     
3.2.2、下載 RabbitMQ、erlang、socat 的安裝包

本次下載的是RabbitMQ-3.6.5版本,采用rpm一鍵安裝,適合新手直接上手。

先創建一個rabbitmq目錄,本例的目錄路徑為/usr/app/rabbitmq,然后在目錄下執行如下命令,下載安裝包!

  • 下載erlang
wget www.rabbitmq.com/releases/erlang/erlang-18.3-1.el7.centos.x86_64.rpm
 
  • 下載socat
wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
 
  • 下載rabbitMQ
wget www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm
 

最終目錄文件如下:

RabbitMQ集群高可用原理及實戰部署是怎樣的  
 
3.2.3、安裝軟件包

下載完之后,按順序依次安裝軟件包,這個很重要哦~

  • 安裝erlang
rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm
 
  • 安裝socat
rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm
 
  • 安裝rabbitmq
rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm
 

安裝完成之后,修改rabbitmq的配置,默認配置文件在/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin目錄下。

vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app
 

修改loopback_users節點的值!

RabbitMQ集群高可用原理及實戰部署是怎樣的  

分別重新命令rabbit節點名稱

vim /etc/rabbitmq/rabbitmq-env.conf
 

在文件里添加一行,如下配置!

NODENAME=rabbit@node1
 

其它兩個節點命令也類似,然后,再保存!通過如下命令,啟動服務即可!

# 啟動服務
rabbitmq-server start &

# 停止服務
rabbitmqctl stop
 

通過如下命令,查詢服務是否啟動成功!

lsof -i:5672
 

如果出現5672已經被監聽,說明已經啟動成功!

RabbitMQ集群高可用原理及實戰部署是怎樣的  
 
3.2.4、啟動可視化的管控臺

輸入如下命令,啟動控制臺!

rabbitmq-plugins enable rabbitmq_management
 

用瀏覽器打開http://ip:15672,這里的ip就是 CentOS 系統的 ip,結果如下:

RabbitMQ集群高可用原理及實戰部署是怎樣的  

賬號、密碼,默認為guest,如果出現無法訪問,檢測防火墻是否開啟,如果開啟將其關閉即可!

登錄之后的監控平臺,界面如下:

RabbitMQ集群高可用原理及實戰部署是怎樣的  
 
3.3、復制 Erlang cookie

RabbitMQ 集群環境下,元數據同步基于 cookie 共享方案實現。

在這里將 node1 的 cookie 文件復制到 node2,由于這個文件權限是 400 為方便傳輸,先修改權限,非必須操作,所以需要先修改 node1 中的該文件權限為 777

chmod 777 /var/lib/rabbitmq/.erlang.cookie
 

用 scp 拷貝到節點 2,節點 3 的操作也類似。

scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/
 

最后,將權限改回來

chmod 400 /var/lib/rabbitmq/.erlang.cookie
     
3.4、組成集群

在節點 2 執行如下命令:

# 停止rabbitmq服務
rabbitmqctl stop_app

# 清空節點狀態
rabbitmqctl reset

# node2和node1構成集群,node2必須能通過node1的主機名ping通
rabbitmqctl join_cluster rabbit@node1

# 開啟rabbitmq服務
rabbitmqctl start_app
 

節點 3 的操作也類似!

在任意一臺機上面查看集群狀態:

rabbitmqctl cluster_status
 
RabbitMQ集群高可用原理及實戰部署是怎樣的  
  • 第一行:表示當前節點信息
  • 第二行:表示集群中的節點成員,disc 表示這些都是磁盤節點
  • 第三行:表示正在運行的節點成員

登錄可視化管控臺,可以很清晰的看到,三個服務節點已經互相關聯起來了!

RabbitMQ集群高可用原理及實戰部署是怎樣的  

如果你想將某個節點移除集群,以移除節點3為例,可以按照如下方式進行操作!

# 首先停止要移除的節點服務
rabbitmqctl stop

# 移除節點3
rabbitmqctl -n rabbit@node1 forget_cluster_node rabbit@node3
 

如果移除之后,無法啟動 rabbitMQ,刪除已有 mnesia 信息!

rm -rf /var/lib/rabbitmq/mnesia
 

然后再次重啟服務即可!

 
3.5、設置內存節點
#加入時候設置節點為內存節點(默認加入的為磁盤節點)
rabbitmqctl join_cluster rabbit@node1 --ram
 

其中--ram指的是作為內存節點,如果不加,那就默認為磁盤節點。

如果節點在集群中已經是磁盤節點了,通過以下命令可以將節點改成內存節點:

# 停止rabbitmq服務
rabbitmqctl stop_app

# 更改節點為內存節點
rabbitmqctl change_cluster_node_type ram

# 開啟rabbitmq服務
rabbitmqctl start_app
 
RabbitMQ集群高可用原理及實戰部署是怎樣的  
 
3.6、鏡像隊列

上面我們提到,在默認情況下,隊列只會保存在其中一個節點上,當節點發生故障時,盡管所有元數據信息都可以從磁盤節點上將元數據恢復到本節點上,但是內存節點的隊列消息內容就不行了,這樣就會導致消息的丟失。

RabbitMQ 很早就意識到這個問題,在 2.6 以后的版本中增加了隊列冗余選項:鏡像隊列

所謂鏡像隊列,其實就是主隊列(master)依然是僅存在于一個節點上,通過關聯的 rabbitMQ 服務器,從主隊列同步消息到各個節點,也就是所謂的主從模式,將主隊列的消息進行備份處理。

如果主隊列沒有發生故障,那么其工作流程跟普通隊列一樣,生產者和消費者不會感知其變化,當發布消息時,依然是路由到主隊列中,而主隊列通過類似廣播的機制,將消息擴散同步至其余從隊列中,這就有點像 fanout 交換器一樣。而消費者依然是從主隊列中讀取消息。

一旦主隊列發生故障,集群就會從最老的一個從隊列選舉為新的主隊列,這也就實現了隊列的高可用了,但我們切記不要濫用這個機制,在上面也說了,隊列的冗余操作會導致不能通過擴展節點增加存儲空間,而且會造成性能瓶頸。

命令格式如下:

rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
 

參數介紹:

-p Vhost: 可選參數,針對指定vhost下的queue進行設置
Name: policy的名稱
Pattern: queue的匹配模式(正則表達式)
Definition: 鏡像定義,包括三個部分ha-mode, ha-params, ha-sync-mode
    ha-mode: 指明鏡像隊列的模式,有效值為 all/exactly/nodes
        all: 表示在集群中所有的節點上進行鏡像
        exactly: 表示在指定個數的節點上進行鏡像,節點的個數由ha-params指定
        nodes: 表示在指定的節點上進行鏡像,節點名稱通過ha-params指定
    ha-params: ha-mode模式需要用到的參數
    ha-sync-mode: 進行隊列中消息的同步方式,有效值為automatic和manual
priority: 可選參數,policy的優先級
 

舉個例子,聲明名為ha-all的策略,它與名稱以ha開頭的隊列相匹配,并將鏡像配置到集群中的所有節點:

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
 

類似操作很多,具體使用可以參考官方 api。

 

四、集群的負載均衡

HAProxy 提供高可用性、負載均衡以及基于TCP和HTTP應用的代理,支持虛擬主機,它是免費、快速并且可靠的一種解決方案。根據官方數據,其最高極限支持10G的并發。HAProxy支持從4層至7層的網絡交換,即覆蓋所有的 TCP 協議。就是說,Haproxy 甚至還支持 Mysql 的均衡負載。為了實現 RabbitMQ 集群的軟負載均衡,這里可以選擇HAProxy。

RabbitMQ集群高可用原理及實戰部署是怎樣的  
 
4.1、HAProxy 安裝

HAProxy 的安裝也很簡單,單獨部署在一臺服務器上,通過如下命令即可安裝完成!

yum install haproxy
 

編輯 HAProxy 配置文件:

vim /etc/haproxy/haproxy.cfg
 

我們只需要在文件末尾加上如下配置即可!

#綁定配置
listen rabbitmq_cluster
        bind 0.0.0.0:5672
        #配置TCP模式
        mode tcp
        #加權輪詢
        balance roundrobin
        #RabbitMQ集群節點配置
        server rmq_node1 197.168.24.206:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node2 197.168.24.233:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node3 197.168.24.234:5672 check inter 5000 rise 2 fall 3 weight 1

#haproxy監控頁面地址
listen monitor
        bind 0.0.0.0:8100
        mode http
        option httplog
        stats enable
        stats uri /stats
        stats refresh 5s
 

綁定配置參數說明:

  • bind:這里定義了客戶端連接連接 IP 地址和端口號,用于客戶端連接
  • balance roundrobin:表示加權輪詢負載均衡算法

RabbitMQ 集群節點配置說明:

  • server rmq_node1:定義HAProxy內RabbitMQ服務的標識
  • 197.168.24.206:5672:標識了后端RabbitMQ的服務地址
  • check inter 5000:表示每隔多少毫秒檢查RabbitMQ服務是否可用,示例參數值為 5000
  • rise 2:表示 RabbitMQ 服務在發生故障之后,需要多少次健康檢查才能被再次確認可用,示例參數值為 2
  • fall 2:表示需要經歷多少次失敗的健康檢查之后,HAProxy 才會停止使用此RabbitMQ服務,示例參數值為 2
  • weight 1:表示權重比例,值越低,會優先進行數據分配,示例參數值為 1

啟動 HAProxy:

/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg
 

登錄http://ip:8100/statsweb 管理界面,即可進行監控查看!

RabbitMQ集群高可用原理及實戰部署是怎樣的  
 

五、Java 客戶端使用

如果是配置了 HAProxy 代理服務器,可以直接使用 HAProxy 代理服務器地址即可!

 //ConnectionFactory創建MQ的物理連接
connectionFactory = new ConnectionFactory();
connectionFactory.setHost("197.168.24.207");  //代理服務器地址
connectionFactory.setPort(5672);          //代理服務器端口
connectionFactory.setUsername("admin");  //guest只能在本機進行訪問,通過代理服務器發送消息時需要重新建立用戶
connectionFactory.setPassword("admin");  //guest
connectionFactory.setVirtualHost("/");    //虛擬主機
 

如果沒有代理服務器,使用SpringCachingConnectionFactory類進行配置。

SpringBoot項目為例,配置文件如下:

spring.rabbitmq.addresses=197.168.24.206:5672,197.168.24.233:5672,197.168.24.234:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
 

RabbitConfig配置類如下:

@Configuration
public class RabbitConfig {

    /**
     * 初始化連接工廠
     * @param addresses
     * @param userName
     * @param password
     * @param vhost
     * @return
     */
    @Bean
    ConnectionFactory connectionFactory(@Value("${spring.rabbitmq.addresses}") String addresses,
                                        @Value("${spring.rabbitmq.username}") String userName,
                                        @Value("${spring.rabbitmq.password}") String password,
                                        @Value("${spring.rabbitmq.virtual-host}") String vhost) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(addresses);
        connectionFactory.setUsername(userName);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(vhost);
        return connectionFactory;
    }

    /**
     * 重新實例化 RabbitAdmin 操作類
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        return new RabbitAdmin(connectionFactory);
    }

    /**
     * 重新實例化 RabbitTemplate 操作類
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate=new RabbitTemplate(connectionFactory);
        //數據轉換為json存入消息隊列
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        return rabbitTemplate;
    }

}

關于RabbitMQ集群高可用原理及實戰部署是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

普陀区| 敦煌市| 宜丰县| 渝中区| 普兰县| 巩留县| 鲁甸县| 大荔县| 宜丰县| 温宿县| 乌兰察布市| 司法| 济南市| 托克逊县| 甘南县| 确山县| 紫阳县| 楚雄市| 山丹县| 伊吾县| 双江| 合阳县| 平安县| 黑山县| 富锦市| 唐海县| 肃北| 乌兰浩特市| 天长市| 河北区| 阳山县| 乌拉特前旗| 上杭县| 青铜峡市| 嘉鱼县| 沭阳县| 巴马| 湖北省| 永平县| 伊宁县| 廊坊市|