消息隊列集群-RabbitMQ
一、消息中間件
中間件
tomcat java web中間件 web容器 mysql
php php mysql
uwsgi python mysql
mycat 數據庫中間件
rabbitMQ 消息中間件
1、簡介
MQ 全稱為(Message Queue消息隊列)。是一種應用程序對應用程序的通信方法。應用程序通過讀寫出入隊列的消息(針對應用程序的數據)來通信,而無需專用連接來鏈接它們。
消息傳遞指的是程序之間通過在消息中發送數據進行通信,而不是通過直接調用彼此來通信。。隊列的使用除去了接收和發送應用程序同時執行的要求。
在項目中,通過提供消息傳遞和消息隊列模型,可以在分布式環境下擴展進程的通信,將一些無需即時返回且耗時的操作提取出來,進行了異步處理,而這種異步處理的方式大大的節省了服務器的請求響應時間,從而提高了系統的吞吐量。
當下主流的消息中間件有RabbitMQ、Kafka、ActiveMQ、RocketMQ等。其能在不同平臺之間進行通信,常用來屏蔽各種平臺協議之間的特性,實現應用程序之間的協同。優點在于能夠在客戶端和服務器之間進行同步和異步的連接,并且在任何時刻都可以將消息進行傳送和轉發,是分布式系統中非常重要的組件,主要用來解決應用耦合、異步通信、流量削峰等問題。
2、作用
1、消息中間件主要作用
-
解耦
-
冗余(存儲)
-
擴展性
-
削峰
-
可恢復性
-
順序保證
-
緩沖
-
異步通信
2、消息中間件的兩種模式
1、P2P模式
P2P模式包含三個角色:消息隊列(Queue)、發送者(Sender)、接收者(Receiver)。每個消息都被發送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留著消息,直到它們被消費或超時。
P2P的特點:
- 每個消息只有一個消費者(Consumer),即一旦被消費,消息就不再在消息隊列中
- 發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送了消息之后,不管接收者有沒有正在運行它不會影響到消息被發送到隊列
- 接收者在成功接收消息之后需向隊列應答成功
- 如果希望發送的每個消息都會被成功處理的話,那么需要P2P模式
2、Pub/Sub模式
Pub/Sub模式包含三個角色:主題(Topic)、發布者(Publisher)、訂閱者(Subscriber) 。多個發布者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。
Pub/Sub的特點:
- 每個消息可以有多個消費者
- 發布者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之后,才能消費發布者的消息
- 為了消費消息,訂閱者必須保持運行的狀態
- 如果希望發送的消息可以不被做任何處理、或者只被一個消費者處理、或者可以被多個消費者處理的話,那么可以采用Pub/Sub模式
3、常用中間件介紹與對比
1、Kafka
Kafka是LinkedIn開 源的分布式發布-訂閱消息系統,目前歸屬于Apache頂級項目。Kafka主要特點是基于Pull的模式來處理消息消費,追求高吞吐量,一開始的目的就是用于日志收集和傳輸。0.8版本開始支持復制,不支持事務,對消息的重復、丟失、錯誤沒有嚴格要求,適合產生大量數據的互聯網服務的數據收集業務。
2、RabbitMQ
RabbitMQ是使用Erlang語言開發的開源消息隊列系統,基于AMQP協議來實現。AMQP的主要特征是面向消息、隊列、路由(包括點對點和發布/訂閱)、可靠性、安全。AMQP協議更多用在企業系統內對數據一致性、穩定性和可靠性要求很高的場景,對性能和吞吐量的要求還在其次。
3、RocketMQ
RocketMQ是阿里開源的消息中間件,它是純Java開發,具有高吞吐量、高可用性、適合大規模分布式系統應用的特點。RocketMQ思路起源于Kafka,但并不是Kafka的一個Copy,它對消息的可靠傳輸及事務性做了優化,目前在阿里集團被廣泛應用于交易、充值、流計算、消息推送、日志流式處理、binglog分發等場景。
RabbitMQ比Kafka可靠,Kafka更適合IO高吞吐的處理,一般應用在大數據日志處理或對實時性(少量延遲)、可靠性(少量丟數據)要求稍低的場景使用,比如ELK日志收集。
二、RabbitMQ 詳解
1、RabbitMQ 介紹
對于一個大型的軟件系統來說,它會有很多subsystem or Component or submodule。
那么這些模塊是如何通信的?
這和傳統的IPC有很大的區別。傳統的IPC很多都是在單一系統上的,模塊耦合性很大,不適合擴展(Scalability),如果使用socket那么不同的模塊的確可以部署到不同的機器上,但還是有很多問題需要解決。
比如:
1)信息的發送者和接收者如何維持這個連接,如果一方的連接中斷,這期間的數據如何防止丟失?
2)如何降低發送者和接收者的耦合度?
3)如何讓Priority高的接收者先接到數據?
4)如何做到load balance?有效均衡接收者的負載?
5)如何有效的將數據發送到相關的接收者?也就是說將接收者subscribe 不同的數據,如何做有效的filter。
6)如何做到可擴展,甚至將這個通信模塊發到cluster上?
7)如何保證接收者接收到了完整,正確的數據?
AMQP協議解決了以上的問題,而RabbitMQ實現了AMQP。
AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,為面向消息的中間件設計。基于此協議的客戶端與消息中間件可傳遞消息,并不受客戶端/中間件不同產品,不同的開發語言等條件的限制。
**RabbitMQ 是一個在 AMQP(Advanced Message Queuing Protocol )基礎上實現的,可復用的企業消息系統。**它可以用于大型軟件系統各個模塊之間的高效通信,支持高并發,支持可擴展。它支持多種客戶端如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX,持久化,用于在分布式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。
RabbitMQ是使用Erlang編寫的一個開源的消息隊列,本身支持很多的協議:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它變的非常重量級,更適合于企業級的開發。它同時實現了一個Broker構架,這意味著消息在發送給客戶端時先在中心隊列排隊,對路由(Routing)、負載均衡(Load balance)或者數據持久化都有很好的支持。
2、RabbitMQ 特點
- 可靠性
- 靈活的路由
- 擴展性
- 高可用性
- 多種協議
- 多語言客戶端
- 管理界面
- 插件機制
3、RabbitMQ 概念及工作原理
- Broker: 簡單來說就是消息隊列服務器實體。
- Exchange: 消息交換機,它指定消息按什么規則,路由到哪個隊列。
- Queue: 消息隊列載體,每個消息都會被投入到一個或多個隊列。
- Binding: 綁定,它的作用就是把exchange和queue按照路由規則綁定起來。
- Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。
- vhost: 虛擬主機,一個broker里可以開設多個vhost,用作不同用戶的權限分離。
- producer: 消息生產者,就是投遞消息的程序。
- consumer:消息消費者,就是接受消息的程序。
- channel: 消息通道,在客戶端的每個連接里,可建立多個channel,每個channel代表一個會話任務。
RabbitMQ從整體上來看是一個典型的生產者消費者模型,主要負責接收、存儲和轉發消息
AMQP模型中,消息在producer中產生,發送到MQ的exchange上,exchange根據配置的路由方式發到相應的Queue上,Queue又將消息發送給consumer,消息從queue到consumer有push和pull兩種方式。
消息隊列的使用過程大概如下:
- 客戶端連接到消息隊列服務器,打開一個channel。
- 客戶端聲明一個exchange,并設置相關屬性。
- 客戶端聲明一個queue,并設置相關屬性。
- 客戶端使用routing key,在exchange和queue之間建立好綁定關系。
- 客戶端投遞消息到exchange。
exchange接收到消息后,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列里。 exchange也有幾個類型,完全根據key進行投遞的叫做Direct交換機,例如,綁定時設置了routing key為"abc",那么客戶端提交的消息,只有設置了key為"abc"的才會投遞到隊列。
三、RabbitMQ 單機部署(了解)
1、安裝 erlang
添加yum支持
[root@qfedu.com ~]# cd /usr/local/src/
[root@qfedu.com ~]# mkdir rabbitmq
[root@qfedu.com ~]# cd rabbitmq
[root@qfedu.com ~]# wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
[root@qfedu.com ~]# rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
[root@qfedu.com ~]# rpm --import http://packages.erlang-solutions.com/rpm/erlang_solutions.asc
[root@qfedu.com ~]# yum install erlang -y
2、安裝RabbitMQ
用 yum 安裝 RabbitMQ
注:直接使用epel源安裝即可
[root@qfedu.com ~]# rpm --import https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
# this example assumes the CentOS 7 version of the package
[root@qfedu.com ~]# yum install rabbitmq-server-3.7.13-1.el7.noarch.rpm
[root@qfedu.com ~]# rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
# this example assumes the CentOS 7 version of the package
[root@qfedu.com ~]# yum install rabbitmq-server-3.7.13-1.el7.noarch.rpm
2、用 rpm 手動安裝
1、下載安裝包
[root@qfedu.com ~]# wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.13/rabbitmq-server-3.7.13-1.el7.noarch.rpm
2、安裝
[root@qfedu.com ~]# rpm -ivh rabbitmq-server-3.7.13-1.el7.noarch.rpm
3、常用命令
[root@qfedu.com ~]# service rabbitmq-server start
[root@qfedu.com ~]# service rabbitmq-server stop
[root@qfedu.com ~]# service rabbitmq-server restart
[root@qfedu.com ~]# chkconfig rabbitmq-server on //設置開機自啟
4、設置配置文件
[root@qfedu.com ~]# cd /etc/rabbitmq
[root@qfedu.com ~]# cp /usr/share/doc/rabbitmq-server-3.7.13/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
5、設置用戶遠程訪問
[root@qfedu.com ~]# vim /etc/rabbitmq/rabbitmq.config
去掉后面的逗號
6、開啟web界面管理工具
[root@qfedu.com ~]# rabbitmq-plugins enable rabbitmq_management
[root@qfedu.com ~]# service rabbitmq-server restart
3、客戶端的簡單介紹
1、界面的介紹
默認用戶名和密碼:guest guest
注意設置虛擬主機與添加用戶這塊。
關于虛擬主機,Virtual Host,其實是一個虛擬概念,類似于權限控制組,一個Virtual Host里面可以有若干個Exchange和Queue,但是權限控制的最小粒度是Virtual Host
2、用戶角色
- 超級管理員(administrator)
可登陸管理控制臺,可查看所有的信息,并且可以對用戶,策略(policy)進行操作。
- 監控者(monitoring)
可登陸管理控制臺,同時可以查看rabbitmq節點的相關信息(進程數,內存使用情況,磁盤使用情況等)
- 略制定者(policymaker)
可登陸管理控制臺, 同時可以對policy進行管理。但無法查看節點的相關信息(上圖紅框標識的部分)。
- 普通管理者(management)
僅可登陸管理控制臺,無法看到節點信息,也無法對策略進行管理。
- 其他
無法登陸管理控制臺,通常就是普通的生產者和消費者。
3、RabbitMQ常用的命令
1、基本命令
- 啟動監控管理器:rabbitmq-plugins enable rabbitmq_management
- 關閉監控管理器:rabbitmq-plugins disable rabbitmq_management
- 啟動rabbitmq:rabbitmq-service start
- 關閉rabbitmq:rabbitmq-service stop
- 查看所有的隊列:rabbitmqctl list_queues
- 清除所有的隊列:rabbitmqctl reset
- 關閉應用:rabbitmqctl stop_app
- 啟動應用:rabbitmqctl start_app
2、用戶和權限設置
- 添加用戶:rabbitmqctl add_user username password
- 分配角色:rabbitmqctl set_user_tags username administrator
- 新增虛擬主機:rabbitmqctl add_vhost vhost_name
- 將新虛擬主機授權給新用戶:
rabbitmqctl set_permissions -p vhost_name username “.*” “.*” “.*”
(后面三個”*”代表用戶擁有配置、寫、讀全部權限)
3、角色說明
- 超級管理員(administrator)
可登陸管理控制臺,可查看所有的信息,并且可以對用戶,策略(policy)進行操作。 - 監控者(monitoring)
可登陸管理控制臺,同時可以查看rabbitmq節點的相關信息(進程數,內存使用情況,磁盤使用情況等) - 策略制定者(policymaker)
可登陸管理控制臺, 同時可以對policy進行管理。但無法查看節點的相關信息(上圖紅框標識的部分)。 - 普通管理者(management)
僅可登陸管理控制臺,無法看到節點信息,也無法對策略進行管理。 - 其他
無法登陸管理控制臺,通常就是普通的生產者和消費者。
四、RabbitMQ 集群部署及配置
RabbitMQ一般以集群方式部署,主要提供消息的接受和發送,實現各微服務之間的消息異步。以下將介紹RabbitMQ+HA方式進行部署。
1、原理介紹
RabbitMQ是依據erlang的分布式特性(RabbitMQ底層是通過Erlang架構來實現的,所以rabbitmqctl會啟動Erlang節點,并基于Erlang節點來使用Erlang系統連接RabbitMQ節點,在連接過程中需要正確的Erlang Cookie和節點名稱,Erlang節點通過交換Erlang Cookie以獲得認證)來實現的,所以部署Rabbitmq分布式集群時要先安裝Erlang,并把其中一個服務的cookie復制到另外的節點。
RabbitMQ集群中,各個RabbitMQ為對等節點,即每個節點均提供給客戶端連接,進行消息的接收和發送。節點分為內存節點和磁盤節點,一般的,均應建立為磁盤節點,為了防止機器重啟后的消息消失;
RabbitMQ的Cluster集群模式一般分為兩種,普通模式和鏡像模式。消息隊列通過RabbitMQ HA鏡像隊列進行消息隊列實體復制。
普通模式下,以兩個節點(rabbit01、rabbit02)為例來進行說明。對于Queue來說,消息實體只存在于其中一個節點rabbit01(或者rabbit02),rabbit01和rabbit02兩個節點僅有相同的元數據,即隊列的結構。當消息進入rabbit01節點的Queue后,consumer從rabbit02節點消費時,RabbitMQ會臨時在rabbit01、rabbit02間進行消息傳輸,把A中的消息實體取出并經過B發送給consumer。所以consumer應盡量連接每一個節點,從中取消息。即對于同一個邏輯隊列,要在多個節點建立物理Queue。否則無論consumer連rabbit01或rabbit02,出口總在rabbit01,會產生瓶頸。
鏡像模式下,將需要消費的隊列變為鏡像隊列,存在于多個節點,這樣就可以實現RabbitMQ的HA高可用性。作用就是消息實體會主動在鏡像節點之間實現同步,而不是像普通模式那樣,在consumer消費數據時臨時讀取。缺點就是,集群內部的同步通訊會占用大量的網絡帶寬。
2、部署 RabbitMQ Cluster
1、Rabbitmq 有 3 種模式,但集群模式是 2 種
詳細如下:
- 單一模式:即單機情況不做集群,就單獨運行一個 rabbitmq 而已。
- 普通模式:默認模式,以兩個節點(rabbit01、rabbit02)為例,對于 Queue 來說,消息實體只存在于其中一個節點 rabbit01(或者 rabbit02),rabbit01 和 rabbit02 兩個節點僅有相同的元數據,即隊列的結構。當消息進入 rabbit01 的 Queue 后,consumer 從 rabbit02 消費時,RabbitMQ 會臨時在 rabbit01、rabbit02 間進行消息傳輸,把 A 中的消息實體取出并經過 B 發送給 consumer。所以 consumer 應盡量連接每一個節點,從中取消息。即對于同一個邏輯隊列,要在多個節點建立物理 Queue。否則無論 consumer 連 rabbit01 或 rabbit02,出口總在 rabbit01,會產生瓶頸。當 rabbit01 節點故障后,rabbit02 節點無法取到 rabbit01 節點中還未消費的消息實體。如果做了消息持久化,那么得等 rabbit01 節點恢復,然后才可被消費;如果沒有持久化的話,就會產生消息丟失的現象。
- 鏡像模式: 把需要的隊列做成鏡像隊列,存在與多個節點屬于 RabbitMQ 的 HA 方案。該模式解決了普通模式中的問題,其實質和普通模式不同之處在于,消息實體會主動在鏡像節點間同步,而不是在客戶端取數據時臨時拉取。該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,集群內部的網絡帶寬將會被這種同步通訊大大消耗掉。所以在對可靠性要求較高的場合中適用。
2、環境準備及軟件安裝
3臺centos7操作系統,ip分別為
192.168.120.138
192.168.120.139
192.168.120.140
修改 hosts 文件 (3 臺)
[root@rabbitmq1 ~]# vim /etc/hosts
192.168.120.138 rabbitmq1
192.168.120.139 rabbitmq2
192.168.120.140 rabbitmq3
安裝 erlang 環境和rabbitmq-server (3 臺)–centos7
[root@rabbitmq1 ~]# yum install -y epel-release && yum -y install erlang socat
[root@rabbitmq1 ~]# yum -y install rabbitmq-server編程:ruby erlang perl python shell c c++ php c# .net js
標記語言: yaml xml html
安裝 erlang 環境和rabbitmq-server (3 臺)–centos-stream 8/9同配
配置官方yum源,本源配置來源于官方網站(Installing on RPM-based Linux (RedHat Enterprise Linux, CentOS, Fedora, openSUSE) — RabbitMQ)
從上面的網頁入口找到如下內容
[root@rabbitmq1 ~]# cat /etc/yum.repos.d/rebbitmq.repo
# In /etc/yum.repos.d/rabbitmq.repo##
## Zero dependency Erlang
##[rabbitmq_erlang]
name=rabbitmq_erlang
baseurl=https://packagecloud.io/rabbitmq/erlang/el/8/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
# PackageCloud's repository key and RabbitMQ package signing key
gpgkey=https://packagecloud.io/rabbitmq/erlang/gpgkeyhttps://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300[rabbitmq_erlang-source]
name=rabbitmq_erlang-source
baseurl=https://packagecloud.io/rabbitmq/erlang/el/8/SRPMS
repo_gpgcheck=1
gpgcheck=0
enabled=1
# PackageCloud's repository key and RabbitMQ package signing key
gpgkey=https://packagecloud.io/rabbitmq/erlang/gpgkeyhttps://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300##
## RabbitMQ server
##[rabbitmq_server]
name=rabbitmq_server
baseurl=https://packagecloud.io/rabbitmq/rabbitmq-server/el/8/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
# PackageCloud's repository key and RabbitMQ package signing key
gpgkey=https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkeyhttps://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300[rabbitmq_server-source]
name=rabbitmq_server-source
baseurl=https://packagecloud.io/rabbitmq/rabbitmq-server/el/8/SRPMS
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
[root@rabbitmq1 ~]# yum install rabbitmq-server -y
啟動服務 (3 臺)
[root@rabbitmq1 ~]# systemctl start rabbitmq-server.service
[root@rabbitmq1 ~]# systemctl stop rabbitmq-server.service
[root@rabbitmq1 ~]# systemctl enable rabbitmq-server.service
[root@rabbitmq1 ~]# systemctl restart rabbitmq-server.service
3、賬號配置
安裝啟動后其實還不能在其它機器訪問,rabbitmq 默認的 guest 賬號只能在本地機器訪問, 如果想在其它機器訪問必須配置其它賬號
配置管理員賬號:
# 可以創建管理員用戶,負責整個 MQ 的運維
[root@rabbitmq1 ~]# rabbitmqctl add_user admin admin
# 賦予其 administrator 角色
[root@rabbitmq1 ~]# rabbitmqctl set_user_tags admin administrator
# 創建 RabbitMQ 監控用戶,負責整個 MQ 的監控
[root@rabbitmq1 ~]# rabbitmqctl add_user user_monitoring passwd_monitor
[root@rabbitmq1 ~]# rabbitmqctl set_user_tags user_monitoring monitoring
# 創建某個項目的專用用戶,只能訪問項目自己的 virtual hosts
[root@rabbitmq1 ~]# rabbitmqctl set_user_tags user_monitoring management
# 創建和賦角色完成后查看并確認
[root@rabbitmq1 ~]# rabbitmqctl list_users
4、啟動 rabbitmq 內置 web 插件, 管理 rabbitmq 賬號等信息 (3 臺)
[root@rabbitmq1 ~]# rabbitmq-plugins enable rabbitmq_management
[root@rabbitmq1 ~]# systemctl restart rabbitmq-server
訪問 http:// 你的地址:15672
centos7使用用戶guest、密碼guest登錄,這個賬戶擁有所有的權限
centos8使用用戶admin、密碼admin登錄
頁面如下:
5、rabbitmq 用戶權限 VirtualHost(部署集群過程中不是必須的)
像 mysql 有數據庫的概念并且可以指定用戶對庫和表等操作的權限。那 RabbitMQ 呢?RabbitMQ 也有類似的權限管理。在 RabbitMQ 中可以虛擬消息服務器 VirtualHost,每個 VirtualHost 相當于一個相對獨立的 RabbitMQ 服務器,每個 VirtualHost 之間是相互隔離的。exchange、queue、message 不能互通。 在 RabbitMQ 中無法通過 AMQP 創建 VirtualHost,可以通過以下命令來創建
[root@rabbitmq1 ~]# rabbitmqctl add_vhost [vhostname]
通常在權限管理中主要包含三步:
1、新建用戶
[root@rabbitmq1 ~]# rabbitmqctl add_user superrd superrd
2、配置權限
set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
[root@rabbitmq1 ~]# rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'
其中,.* 的位置分別用正則表達式來匹配特定的資源,如:
'^(amq.gen.*|amq.default)$'
可以匹配 server 生成的和默認的 exchange,’^$’不匹配任何資源
- exchange 和 queue 的 declare 與 delete 分別需要 exchange 和 queue 上的配置權限
- exchange 的 bind 與 unbind 需要 exchange 的讀寫權限
- queue 的 bind 與 unbind 需要 queue 寫權限 exchange 的讀權限 發消息 (publish) 需 exchange 的寫權限
- 獲取或清除 (get、consume、purge) 消息需 queue 的讀權限
示例:我們賦予 superrd 在“/”下面的全部資源的配置和讀寫權限。
[root@rabbitmq1 ~]# rabbitmqctl set_permissions -p / superrd ".*" ".*" ".*"
注意”/”代表 virtual host 為“/”這個“/”和 linux 里的根目錄是有區別的并不是 virtual host 為“/”可以訪問所以的 virtual host,把這個“/”理解成字符串就行。
需要注意的是 RabbitMQ 會緩存每個 connection 或 channel 的權限驗證結果、因此權限發生變化后需要重連才能生效。
3、查看權限
[root@rabbitmq1 ~]# rabbitmqctl list_user_permissions admin
[root@rabbitmq1 ~]# rabbitmqctl list_permissions -p /
4、配置角色
[root@rabbitmq1 ~]# rabbitmqctl set_user_tags [user] [role]
RabbitMQ 中的角色分為如下五類:none、management、policymaker、monitoring、administrator
官方解釋如下:
management
User can access the management plugin
policymaker
User can access the management plugin and manage policies and parameters for the vhosts they have access to.
monitoring
User can access the management plugin and see all connections and channels as well as node-related information.
administrator
User can do everything monitoring can do, manage users, vhosts and permissions, close other user’s connections, and manage policies and parameters for all vhosts.
- none 不能訪問 management plugin
- management 用戶可以通過 AMQP 做的任何事外加: 列出自己可以通過 AMQP 登入的 virtual hosts 查看自己的 virtual hosts 中的 queues, exchanges 和 bindings 查看和關閉自己的 channels 和 connections 查看有關自己的 virtual hosts 的“全局”的統計信息,包含其他用戶在這些 virtual hosts 中的活動。
- policymaker management 可以做的任何事外加: 查看、創建和刪除自己的 virtual hosts 所屬的 policies 和 parameters
- monitoring management 可以做的任何事外加: 列出所有 virtual hosts,包括他們不能登錄的 virtual hosts 查看其他用戶的 connections 和 channels 查看節點級別的數據如 clustering 和 memory 使用情況 查看真正的關于所有 virtual hosts 的全局的統計信息
- administrator policymaker 和 monitoring 可以做的任何事外加: 創建和刪除 virtual hosts 查看、創建和刪除 users 查看創建和刪除 permissions 關閉其他用戶的 connections
如下示例將 superrd 設置成 administrator 角色。
[root@rabbitmq1 ~]# rabbitmqctl set_user_tags superrd administrator
3、搭建 rabbitmq 的一般模式集群
在上述的 3 臺機器上安裝 rabbitmq 完成之后,你可以看到你的機器中有如下 1 個文件。路徑在 $HOME 中或者在 /var/lib/rabbitmq 中,文件名稱為.erlang.cookie, 他是一個隱藏文件。那么這文件存儲的內容是什么,是做什么用的呢?
RabbitMQ 的集群是依賴 erlang 集群,而 erlang 集群是通過這個 cookie 進行通信認證的,因此我們做集群的第一步就是干 cookie。
1、統一 erlang.cookie 文件中 cookie 值
必須使集群中也就是rabbitmq2,rabbitmq3這兩臺機器的.erlang.cookie 文件中 cookie 值一致,且權限為 owner 只讀。
# 復制 rabbitmq1 中 /var/lib/rabbitmq/.erlang.cookie 的內容到 rabbitmq2 rabbitmq3 相同的內容
[root@rabbitmq2 ~]# chmod 600 /var/lib/rabbitmq/.erlang.cookie
2、查看集群狀態
我的是已經做好的
[root@rabbitmq1 rabbitmq]# rabbitmqctl status
Status of node rabbit@rabbitmq1
[{pid,17572},{running_applications,[{rabbitmq_management,"RabbitMQ Management Console","3.6.15"},{rabbitmq_web_dispatch,"RabbitMQ Web Dispatcher","3.6.15"},{rabbitmq_management_agent,"RabbitMQ Management Agent","3.6.15"},{rabbit,"RabbitMQ","3.6.15"},{amqp_client,"RabbitMQ AMQP Client","3.6.15"},{rabbit_common,"Modules shared by rabbitmq-server and rabbitmq-erlang-client","3.6.15"},{recon,"Diagnostic tools for production use","2.3.2"},{os_mon,"CPO CXC 138 46","2.2.14"},{cowboy,"Small, fast, modular HTTP server.","1.0.4"},{ranch,"Socket acceptor pool for TCP protocols.","1.3.2"},{ssl,"Erlang/OTP SSL application","5.3.3"},{public_key,"Public key infrastructure","0.21"},{cowlib,"Support library for manipulating Web protocols.","1.0.2"},{crypto,"CRYPTO version 2","3.2"},{inets,"INETS CXC 138 49","5.9.8"},{mnesia,"MNESIA CXC 138 12","4.11"},{compiler,"ERTS CXC 138 10","4.9.4"},{xmerl,"XML parser","1.3.6"},{syntax_tools,"Syntax tools","1.6.13"},{asn1,"The Erlang ASN1 compiler version 2.0.4","2.0.4"},{sasl,"SASL CXC 138 11","2.3.4"},{stdlib,"ERTS CXC 138 10","1.19.4"},{kernel,"ERTS CXC 138 10","2.16.4"}]},{os,{unix,linux}},{erlang_version,"Erlang R16B03-1 (erts-5.10.4) [source] [64-bit] [smp:2:2] [async-threads:64] [hipe] [kernel-poll:true]\n"},{memory,[{connection_readers,0},{connection_writers,0},{connection_channels,0},{connection_other,2800},{queue_procs,2800},{queue_slave_procs,0},{plugins,1471200},{other_proc,23282232},{metrics,142320},{mgmt_db,526352},{mnesia,84160},{other_ets,2372704},{binary,890656},{msg_index,40536},{code,27114499},{atom,992409},{other_system,22458876},{allocated_unused,9790936},{reserved_unallocated,2389504},{total,91561984}]},{alarms,[]},{listeners,[{clustering,25672,"::"},{amqp,5672,"::"},{http,15672,"::"}]},{vm_memory_calculation_strategy,rss},{vm_memory_high_watermark,0.4},{vm_memory_limit,1589890252},{disk_free_limit,50000000},{disk_free,33908043776},{file_descriptors,[{total_limit,204700},{total_used,2},{sockets_limit,184228},{sockets_used,0}]},{processes,[{limit,1048576},{used,330}]},{run_queue,0},{uptime,2934},{kernel,{net_ticktime,60}}][root@rabbitmq1 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq1
[{nodes,[{disc,[rabbit@rabbitmq1]},{ram,[rabbit@rabbitmq3,rabbit@rabbitmq2]}]},{running_nodes,[rabbit@rabbitmq3,rabbit@rabbitmq2,rabbit@rabbitmq1]},{cluster_name,<<"rabbit_cluster">>},{partitions,[]},{alarms,[{rabbit@rabbitmq3,[]},{rabbit@rabbitmq2,[]},{rabbit@rabbitmq1,[]}]}]
[root@rabbitmq1 rabbitmq]#
3、Rabbitmq 集群添加節點
重啟 rabbitmq1機器中 rabbitmq 的服務
在 rabbitmq2,rabbitmq3 分別執行
[root@rabbitmq2 ~]# systemctl restart rabbitmq-server.service
[root@rabbitmq2 ~]# rabbitmqctl stop_app
[root@rabbitmq2 ~]# rabbitmqctl join_cluster --ram rabbit@rabbitmq1
[root@rabbitmq2 ~]# rabbitmqctl start_app
[root@rabbitmq2 ~]# rabbitmq-plugins enable rabbitmq_management
4、打開網頁管理頁面查看 nodes
如此便可以啦,你可以做下測試,驗證下我們序言中說的普通模式的說明,那必須是杠杠對的。
4、搭建 rabbitmq 的鏡像高可用模式集群
這一節要參考的文檔是:http://www.rabbitmq.com/ha.html
首先鏡像模式要依賴policy模塊,這個模塊是做什么用的呢?
policy中文來說是政策,策略的意思,那么他就是要設置,那些Exchanges或者queue的數據需要復制,同步,如何復制同步?對就是做這些的。
[root@rabbitmq1 ~]# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
參數意思為:
ha-all:為策略名稱。
:為匹配符,只有一個代表匹配所有,^zlh為匹配名稱為zlh的exchanges或者queue。
ha-mode:為匹配類型,他分為3種模式:
- all-所有(所有的 queue),
- exctly-部分(需配置ha-params參數,此參數為int類型比如3,眾多集群中的隨機3臺機器),
- nodes-指定(需配置ha-params參數,此參數為數組類型比如[“3rabbit@F”,“rabbit@G”]這樣指定為F與G這2臺機器。)。
參考示例如下
當然在web管理界面也能配置:
配置完看隊列如下,其中表示ha-haall的說明用我的ha-haall策略啦,屬于鏡像模式,沒有表示的就是普通模式:
五、Rabbitmq 附錄
RabbitMQ 常用的三種自定義服務器的通用方法:
- 配置文件 rabbitmq.conf
- 環境變量文件 rabbitmq-env.conf
- 補充配置文件 advanced.config
rabbitmq.conf和rabbitmq-env.conf的位置
- 在二進制安裝中路徑是在 :安裝目錄下的/etc/rabbitmq/
- rpm 安裝: /etc/rabbitmq/
如果rabbitmq.conf和rabbitmq-env.conf 的兩個文件不存在,那么我們可以創建該文件,然后我們可以通過環境變量
指定該文件的位置。
補充 :
- rabbitmqctl rabbitmqctl 是管理虛擬主機和用戶權限的工具
- rabbitmq-plugins 是管理插件的工具
1、 rabbitmq.conf
在rabbitmq 3.7.0 之前,rabbitmq.conf 使用了Erlang語法配置格式,新的版本使用了sysctl 格式.
sysctl 語法:
- 單個信息都在一行里面
- 配置信息以key value 的形式保存。
- ‘#’開頭表示注釋。
配置示例文件:rabbitmq.conf.example
配置屬性和描述(官網鏈接)
屬性 | 描述 | 默認值 |
---|---|---|
listeners | 要監聽 AMQP 0-9-1 and AMQP 1.0 的端口 | listeners.tcp.default = 5672 |
num_acceptors.tcp | 接受tcp連接的erlang 進程數 | num_acceptors.tcp = 10 |
handshake_timeout | AMQP 0-9-1 超時時間,也就是最大的連接時間,單位毫秒 | handshake_timeout = 10000 |
listeners.ssl | 啟用TLS的協議 | 默認值為none |
num_acceptors.ssl | 接受基于TLS協議的連接的erlang 進程數 | num_acceptors.ssl = 10 |
ssl_options | TLS 配置 | ssl_options =none |
ssl_handshake_timeout | TLS 連接超時時間 單位為毫秒 | ssl_handshake_timeout = 5000 |
vm_memory_high_watermark | 觸發流量控制的內存閾值,可以為相對值(0.5),或者絕對值 vm_memory_high_watermark.relative = 0.6 ,vm_memory_high_watermark.absolute = 2GB | 默認vm_memory_high_watermark.relative = 0.4 |
vm_memory_calculation_strategy | 內存使用報告策略,assigned:使用Erlang內存分配器統計信息 rss:使用操作系統RSS內存報告。這使用特定于操作系統的方法,并可能啟動短期子進程。legacy:使用遺留內存報告(運行時認為將使用多少內存)。這種策略相當不準確。erlang 與legacy一樣 是為了向后兼容 | vm_memory_calculation_strategy = allocated |
vm_memory_high_watermark_paging_ratio | 當內存的使用達到了50%后,隊列開始將消息分頁到磁盤 | vm_memory_high_watermark_paging_ratio = 0.5 |
total_memory_available_override_value | 該參數用于指定系統的可用內存總量,一般不使用,適用于在容器等一些獲取內存實際值不精確的環境 | 默認未設置 |
disk_free_limit | Rabbitmq存儲數據的可用空間限制,當低于該值的時候,將觸發流量限制,設置可參考vm_memory_high_watermark參數 | disk_free_limit.absolute = 50MB |
log.file.level | 控制記錄日志的等級,有info,error,warning,debug | log.file.level = info |
channel_max | 最大通道數,但不包含協議中使用的特殊通道號0,設置為0表示無限制,不建議使用該值,容易出現channel泄漏 | channel_max = 2047 |
channel_operation_timeout | 通道操作超時,單位為毫秒 | channel_operation_timeout = 15000 |
heartbeat | 表示連接參數協商期間服務器建議的心跳超時的值。如果兩端都設置為0,則禁用心跳,不建議禁用 | heartbeat = 60 |
default_vhost | rabbitmq安裝后啟動創建的虛擬主機 | default_vhost = / |
default_user | 默認創建的用戶名 | default_user = guest |
default_pass | 默認用戶的密碼 | default_pass = guest |
default_user_tags | 默認用戶的標簽 | default_user_tags.administrator = true |
default_permissions | 在創建默認用戶是分配給默認用戶的權限 | default_permissions.configure = .* default_permissions.read = .* default_permissions.write = .* |
loopback_users | 允許通過回環地址連接到rabbitmq的用戶列表,如果要允許guest用戶遠程連接(不安全)請將該值設置為none,如果要將一個用戶設置為僅localhost連接的話,配置loopback_users.username =true(username要替換成用戶名) | loopback_users.guest = true(默認為只能本地連接) |
cluster_formation.classic_config.nodes | 設置集群節點cluster_formation.classic_config.nodes.1 = rabbit@hostname1 | |
cluster_formation.classic_config.nodes.2 = rabbit@hostname2 | 默認為空,未設置 | |
collect_statistics | 統計收集模式,none 不發出統計信息事件,coarse每個隊列連接都發送統計一次,fine每發一條消息的統計數據 | collect_statistics = none |
collect_statistics_interval | 統計信息收集間隔,以毫秒為單位 | collect_statistics_interval = 5000 |
delegate_count | 用于集群內通信的委托進程數。在多核的服務器上我們可以增加此值 | delegate_count = 16 |
tcp_listen_options | 默認的套接字選項 | tcp_listen_options.backlog = 128 … |
hipe_compile | 設置為true以使用HiPE預編譯RabbitMQ的部分,HiPE是Erlang的即時編譯器,啟用HiPE可以提高吞吐量兩位數,但啟動時會延遲幾分鐘。Erlang運行時必須包含HiPE支持。如果不是,啟用此選項將不起作用。HiPE在某些平臺上根本不可用,尤其是Windows。 | hipe_compile = false |
cluster_keepalive_interval | 節點應該多長時間向其他節點發送keepalive消息(以毫秒為單位),keepalive的消息丟失不會被視為關閉 | cluster_keepalive_interval = 10000 |
queue_index_embed_msgs_below | 消息的字節大小,低于該大小,消息將直接嵌入隊列索引中 bytes | queue_index_embed_msgs_below = 4096 |
mnesia_table_loading_retry_timeout | 等待集群中Mnesia表可用的超時時間,單位毫秒 | mnesia_table_loading_retry_timeout = 30000 |
mnesia_table_loading_retry_limit | 集群啟動時等待Mnesia表的重試次數,不適用于Mnesia升級或節點刪除。 | mnesia_table_loading_retry_limit = 10 |
mirroring_sync_batch_size | 要在隊列鏡像之間同步的消息的批處理大小 | mirroring_sync_batch_size = 4096 |
queue_master_locator | 隊列主節點的策略,有三大策略 min-masters,client-local,random | queue_master_locator = client-local |
proxy_protocol | 如果設置為true ,則連接需要通過反向代理連接,不能直連接 | proxy_protocol = false |
management.listener.port | rabbitmq web管理界面使用的端口 | management.listener.port = 15672 |
查看rabbitmq的有效配置
[root@rabbitmq1 ~]# rabbitmqctl environment
2、advanced.config
示例文件
某些配置設置不可用或難以使用sysctl格式進行配置。因此,可以使用Erlang術語格式的其他配置文件advanced.config
它將與rabbitmq.conf 文件中提供的配置合并。
配置屬性和描述(官網鏈接)
屬性 | 描述 | 默認值 |
---|---|---|
msg_store_index_module | 設置隊列索引使用的模塊 | {rabbit,[ {msg_store_index_module,rabbit_msg_store_ets_index} ]} |
backing_queue_module | 隊列內容的實現模塊。 | {rabbit,[ {backing_queue_module,rabbit_variable_queue} ]} |
msg_store_file_size_limit | 消息儲存的文件大小,現有的節點更改是危險的,可能導致數據丟失 | 默認值16777216 |
trace_vhosts | 內部的tracer使用,不建議更改 | {rabbit,[ {trace_vhosts,[]} ]} |
msg_store_credit_disc_bound | 設置消息儲存庫給隊列進程的積分,默認一個隊列進程被賦予4000個消息積分 | {rabbit, [{msg_store_credit_disc_bound, {4000, 800}}]} |
queue_index_max_journal_entries | 隊列的索引日志超過該閾值將刷新到磁盤 | {rabbit, [{queue_index_max_journal_entries, 32768}]} |
lazy_queue_explicit_gc_run_operation_threshold | 在內存壓力下為延遲隊列設置的值,該值可以觸發垃圾回收和減少內存使用,降低該值,會降低性能,提高該值,會導致更高的內存消耗 | {rabbit,[{lazy_queue_explicit_gc_run_operation_threshold, 1000}]} |
queue_explicit_gc_run_operation_threshold | 在內存壓力下,正常隊列設置的值,該值可以觸發垃圾回收和減少內存使用,降低該值,會降低性能,提高該值,會導致更高的內存消耗 | {rabbit, [{queue_explicit_gc_run_operation_threshold, 1000}]} |
3、rabbitmq-env.conf
官網鏈接
通過rabbitmq-env.conf 來定義環境變量
RABBITMQ_NODENAME 指定節點名稱
屬性 | 描述 | 默認值 |
---|---|---|
RABBITMQ_NODE_IP_ADDRESS | 綁定的網絡接口 | 默認為空字符串表示綁定本機所有的網絡接口 |
RABBITMQ_NODE_PORT | 端口 | 默認為5672 |
RABBITMQ_DISTRIBUTION_BUFFER_SIZE | 節點之間通信連接的數據緩沖區大小 | 默認為128000,該值建議不要使用低于64MB |
RABBITMQ_IO_THREAD_POOL_SIZE | 運行時用于io的線程數 | 建議不要低于32,linux默認為128 ,windows默認為64 |
RABBITMQ_NODENAME | rabbitmq節點名稱,集群中要注意節點名稱唯一 | linux 默認節點名為 rabbit@$hostname |
RABBITMQ_CONFIG_FILE | rabbitmq 的配置文件路徑,注意不要加文件的后綴(.conf) | 默認 $RABBITMQ_HOME/etc/rabbitmq/rabbitmq(二進制安裝) /etc/rabbitmq/rabbitmq(rpm 安裝) |
RABBITMQ_ADVANCED_CONFIG_FILE | advanced.config文件路徑 | 默認 $RABBITMQ_HOME/etc/rabbitmq/advanced(二進制安裝) /etc/rabbitmq/advanced(rpm 安裝) |
RABBITMQ_CONF_ENV_FILE | 環境變量配置文件路徑 | 默認 $RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf(二進制安裝) /etc/rabbitmq/rabbitmq-env.conf(rpm 安裝) |
RABBITMQ_SERVER_CODE_PATH | 在使用HiPE 模塊時需要使用 | 默認為空 |
RABBITMQ_LOGS | 指定日志文件位置 | 默認為 $RABBITMQ_HOME/etc/var/log/rabbitmq/ |
網絡設置 http://www.rabbitmq.com/networking.html
RABBITMQ_DISTRIBUTION_BUFFER_SIZE 節點間通信緩沖區大小,默認值 128Mb,節點流量比較多的集群中,可以提升該值,建議該值不要低于64MB。
tcp 緩存區大小
下示例將AMQP 0-9-1連接的TCP緩沖區設置為192 KiB:
tcp_listen_options.backlog = 128
tcp_listen_options.nodelay = true
tcp_listen_options.linger.on = true
tcp_listen_options.linger.timeout = 0
tcp_listen_options.sndbuf = 196608
tcp_listen_options.recbuf = 196608
4、在生產環境中不適用的策略
官網鏈接
1、 vhost
在生產中,如果rabbitmq只為單個系統提供服務的時候,我們使用默認的(/)是可以的。在為多個系統提供的服務時,我們建議使用單獨的vhost.
2、 user
對于生產環境,請刪除默認用戶(guest),默認用戶只能從localhost 連接。
我們可以創建指定權限的單獨用戶為每個應用提供服務。對于開啟權限用戶來說,我們可以使用證書,和源ip地址過濾,和身份驗證。來加強安全性。
3、最大打開文件限制
在生產環境我們可能需要調整一些系統的默認限制,以便處理大量的并發連接和隊列。
需要調整的值有打開的最大文件數。在生產環境為rabbitmq 運行的用戶設定為65536,但是對于大多數開發環境來說,4096就已經足夠了。
查看默認的打開文件的最大數量。
[root@rabbitmq1 ~]# ulimit -n
1、臨時修改
[root@rabbitmq1 ~]# ulimit -n 65536
2、永久修改
- 2.1如果是systemed 來進行管理的話我們可以編輯systemed配置文件來進行控制
[service]
LimitNOFILE=300000
-
2.2 如果不是systemed 來進行管理的話,我們可以更改rabbitmq的啟動加載的環境配置文件 rabbitmq-env.conf。在里面開頭添加ulimit -S -n 4096,但該值不能超過系統的默認值的最大值。
[root@rabbitmq1 ~]# ulimit -S -n 4096
-
2.3 系統級別更改
更改配置文件:/etc/security/limits.conf
在文件末尾前面加入
rabbitmq(啟動的用戶名) - nofile 65536
如果更改前用戶已經登錄的話,需要重新登錄下才能生效。
3、內存
當rabbitmq 檢測到它使用的內存超過系統的40%,它將不會接受任何新的消息,這個值是由參數 vm_memory_high_watermark來控制的,默認值是一個安全的值,修改該值需要注意。 rabbitmq 的至少需要128MB,建議vm_memory_high_watermark 值為 0.4~0…66 ,不要使用大于0.7的值。
4、磁盤
磁盤默認的儲存數據閾值是50MB,當低于該值的時候,將觸發流量限制。50MB 只適用于開發環境,生產環境需要調高該值,不然容易由磁盤空間不足導致節點故障,也可能導致數據丟失。
在生產環境中我們設置的值
- 建議的最小值 {disk_free_limit, {mem_relative, 1.0}}
它是基于mem_relative的值,例如在具有4GB內存的rabbitmq主機上,那么該磁盤的閾值就是4G,如果磁盤可用空間低于4G,所有生產者和消息都將拒絕。在允許恢復發布之前,通常需要消費者將隊列消息消費完。
- 建議的更安全值 {disk_free_limit, {mem_relative, 1.5}}
在具有4GB內存的RabbitMQ節點上,如果可用磁盤空間低于6GB,則所有新消息都將被阻止,但是如果我們在停止的時候rabbitmq需要儲存4GB的數據到磁盤,再下一次啟動的時候,就只有2G空間了。
- 建議的最大值 {disk_free_limit, {mem_relative, 2.0}}
這個是最安全的值,如果你的磁盤有足夠多的空間話,建議設置該值。但該值容易觸發警告,因為在具有4GB內存的rabbitmq主機上,需要最低空間大于8G,如果你的磁盤空間比較少的話,不建議設置該值。
5、連接
少使用短連接,使用連接池或者長連接。
6、TLS
建議盡可能使用TLS連接,使用TLS會對傳輸的數據加密,但是對系統的吞吐量產生很大的影響
7、更改默認端口
我們常用的web界面的端口 15672 和AMQP 0-9-1 協議端口 5672 ,建議更改,web界面更改,配置參數 management.listener.port ,AMQP 0-9-1 協議端口配置參數 listeners.tcp.default。