歡迎訪問個人我的主頁 qupzhi.com ,轉載請註明出處。html
本次學習主要針對運維人員,和對rabbitmq不熟悉的開發人員。經過本次學習你將掌握rabbitmq 的基本原理、集羣、基本運維操做、常見故障處理node
用時:25 分鐘linux
用時:9 分鐘json
AMQP,即Advanced Message Queuing Protocol,高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。消息中間件主要用於組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。安全
AMQP的主要特徵是面向消息、隊列、路由(包括點對點和發佈/訂閱)、可靠性、安全。 RabbitMQ是一個開源的AMQP實現,服務器端用Erlang語言編寫,支持多種客戶端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用於在分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。bash
RabbitMQ就是當前最主流的消息中間件之一。服務器
Queue(隊列)是RabbitMQ的內部對象,用於存儲消息,用下圖表示。 cookie
RabbitMQ中的消息都只能存儲在Queue中,生產者(下圖中的P)生產消息並最終投遞到Queue中,消費者(下圖中的C)能夠從Queue中獲取消息並消費。多個消費者能夠訂閱同一個Queue,這時Queue中的消息會被平均分攤給多個消費者進行處理,而不是每一個消費者都收到全部的消息並處理。 網絡
在AMQP模型中,Exchange是接受生產者消息並將消息路由到消息隊列的關鍵組件。ExchangeType和Binding決定了消息的路由規則。因此生產者想要發送消息,首先必需要聲明一個Exchange和該Exchange對應的Binding。架構
在Rabbit MQ中,聲明一個Exchange須要三個參數:ExchangeName,ExchangeType和Durable。ExchangeName是該Exchange的名字,該屬性在建立Binding和生產者經過publish推送消息時須要指定。ExchangeType,指Exchange的類型,在RabbitMQ中,有三種類型的Exchange:direct ,fanout和topic,不一樣的Exchange會表現出不一樣路由行爲。Durable是該Exchange的持久化屬性,這個會在消息持久化章節討論。
聲明一個Binding須要提供一個QueueName,ExchangeName和BindingKey。
下面是消息發送的過程Direct exchange 直接轉發路由,其實現原理是經過消息中的routkey,與queue 中的routkey 進行比對,若兩者匹配,則將消息發送到這個消息隊列。一般使用這個。
以上圖的配置爲例,咱們以routingKey=」error」發送消息到Exchange,則消息會路由到Queue1(amqp.gen-S9b…,這是由RabbitMQ自動生成的Queue名稱)和Queue2(amqp.gen-Agl…);若是咱們以routingKey=」info」或routingKey=」warning」來發送消息,則消息只會路由到Queue2。若是咱們以其餘routingKey發送消息,則消息不會路由到這兩個Queue中。Fanout exchange 複製分發路由,該路由不須要routkey,當exchange收到消息後,將消息複製多份轉發給與本身綁定的消息隊列。
須要注意的一點只有queue具備 保持消息的功能,exchange不能保存消息。
D
,就是持久化隊列,英文durable(持久的)用時:5 分鐘
RabbitMQ能夠經過三種方法來部署分佈式集羣系統,分別是:cluster,federation,shovel
cluster:
federation:應用於廣域網,容許單臺服務器上的交換機或隊列接收發布到另外一臺服務器上交換機或隊列的消息,能夠是單獨機器或集羣。federation隊列相似於單向點對點鏈接,消息會在聯盟隊列之間轉發任意次,直到被消費者接受。一般使用federation來鏈接internet上的中間服務器,用做訂閱分發消息或工做隊列。
shovel:鏈接方式與federation的鏈接方式相似,但它工做在更低層次。能夠應用於廣域網
RabbitMQ集羣會始終同步四種類型的內部元數據(相似索引):
一,存儲空間,若是每一個集羣節點都擁有全部Queue的徹底數據拷貝,那麼每一個節點的存儲空間會很是大,集羣的消息積壓能力會很是弱(沒法經過集羣節點的擴容提升消息積壓能力); 二,性能,消息的發佈者須要將消息複製到每個集羣節點,對於持久化消息,網絡和磁盤同步複製的開銷都會明顯增長。
爲何RabbitMQ不將隊列複製到集羣裏每一個節點呢?這與它的集羣的設計本意相沖突,集羣的設計目的就是增長更多節點時,能線性的增長性能(CPU、內存)和容量(內存、磁盤)。固然RabbitMQ新版本集羣也支持隊列複製(有個選項能夠配置)。好比在有五個節點的集羣裏,能夠指定某個隊列的內容在2個節點上進行存儲,從而在性能與高可用性之間取得一個平衡(應該就是指鏡像模式)。
鏡像模式:其實質和普通模式不一樣之處在於,消息實體會主動在鏡像節點間同步,而不是在consumer取數據時臨時拉取。該模式帶來的反作用也很明顯,除了下降系統性能外,若是鏡像隊列數量過多,加之大量的消息進入,集羣內部的網絡帶寬將會被這種同步通信大大消耗掉。因此在對可靠性要求較高的場合中適用.
RAM node:內存節點將全部的隊列、交換機、綁定、用戶、權限和vhost的元數據定義存儲在內存中,好處是可使得像交換機和隊列聲明等操做更加的快速。
Disk node:將元數據存儲在磁盤中,單節點系統只容許磁盤類型的節點,防止重啓RabbitMQ的時候,丟失系統的配置信息。
Erlang Cookie是保證不一樣節點能夠相互通訊的密鑰,要保證集羣中的不一樣節點相互通訊必須共享相同的Erlang Cookie。具體的目錄存放在/var/lib/rabbitmq/.erlang.cookie
。
用時:8 分鐘
#編輯配置路徑 /etc/rabbitmq/rabbitmq-env.conf
NODE_IP_ADDRESS=172.16.136.133
複製代碼
#配置文件1所在路徑 /etc/rabbitmq/rabbitmq.config (若是是集羣,每臺機器都須要修改這個綁定本機實體ip)
#其中rabbit@master是建立集羣時所配置的參數,@後面的參數爲主機名,示例中爲master
[
{rabbit, [
{cluster_nodes, {['rabbit@master'], disc}},
{cluster_partition_handling, ignore},
{default_user, <<"guest">>},
{default_pass, <<"guest">>},
{tcp_listen_options, [binary,
{packet, raw},
{reuseaddr, true},
{backlog, 128},
{nodelay, true},
{exit_on_close, false},
{keepalive, true}]}
]},
{kernel, [
{inet_dist_listen_max, 44001},
{inet_dist_listen_min, 44001}
]}
].
複製代碼
#配置文件2 所在路徑 /etc/hosts (若是是集羣,每臺機器都須要修改這個綁定本機實體ip,並且hosts文件的映射不得重複,若是重複linux系統爲以最下面一條記錄爲準)
172.16.136.133 master
172.16.136.134 venus
172.16.136.135 venus2
複製代碼
#機器A
service rabbitmq-server stop
epmd -kill
#機器B
service rabbitmq-server stop
epmd -kill
#機器C
service rabbitmq-server stop
epmd -kill
複製代碼
方式1
#機器A
service rabbitmq-server start
#機器B
service rabbitmq-server start
#機器C
service rabbitmq-server start
複製代碼
方式2
rabbitmq-server -detached
複製代碼
集羣重啓的順序是固定的,而且是相反的。 以下所述:
啓動順序:磁盤節點 => 內存節點 關閉順序:內存節點 => 磁盤節點 最後關閉必須是磁盤節點,否則可能回形成集羣啓動失敗、數據丟失等異常狀況。
注1:此處的mq集羣重建是比較快速和有效的方法,面向的是初次安裝或者能夠接受mq中所存有的數據丟失的狀況下,必須先有mq的.json後綴的配置文件或者有把握寫入集羣中exchange、queue等配置。
#機器A
service rabbitmq-server stop
epmd -kill
#機器B
service rabbitmq-server stop
epmd -kill
#機器C
service rabbitmq-server stop
epmd -kill
複製代碼
#位於 /var/lib/rabbitmq/mensia
mv /var/lib/rabbitmq/mensia /var/lib/rabbitmq/mensia.bak
複製代碼
#機器C
service rabbitmq-server start
#機器B
service rabbitmq-server start
#機器A
service rabbitmq-server start
複製代碼
好比A、B、C三臺機器,將B和C加入到A中去,須要執行如下命令
#機器B
rabbitmqctl stop_app
#機器C
rabbitmqctl stop_app
複製代碼
注意此處master爲惟一沒有執行
rabbitmqctl stop_app
的機器
#機器B
rabbitmqctl join_cluster rabbit@master
#機器C
rabbitmqctl join_cluster rabbit@master
複製代碼
#機器B
rabbitmqctl start_app
#機器C
rabbitmqctl start_app
複製代碼
在任意一臺機器上執行rabbitmqctl cluster_status
命令便可檢查,輸出包含集羣中的節點與運行中的節點,兼以主機名標誌
例子中建立了兩個用戶 添加用戶
add_user
,設置角色set_user_tags
,添加rabbitmq虛擬主機add_vhost
,設置訪問權限set_permissions
,如下是詳細用法
# 建立第一個用戶
/usr/sbin/rabbitmqctl add_user 用戶名 密碼
/usr/sbin/rabbitmqctl set_user_tags 用戶名 administrator
/usr/sbin/rabbitmqctl set_permissions -p / 用戶名 ".*" ".*" ".*"
# 建立第二個用戶
/usr/sbin/rabbitmqctl add_user 用戶名2 密碼
/usr/sbin/rabbitmqctl set_user_tags 用戶名2 management
/usr/sbin/rabbitmqctl add_vhost sip_ext
/usr/sbin/rabbitmqctl set_permissions -p sip_ext 用戶名2 '.*' '.*' '.*'
複製代碼
備註:RabbitMQ 虛擬主機,RabbitMQ 經過虛擬主機(vhost)來分發消息。擁有本身獨立的權限控制,不一樣的vhost之間是隔離的,單獨的。
權限控制的基本單位:vhost。
用戶只能訪問與之綁定的vhost。
vhost是AMQP中惟一沒法經過協議來建立的基元。只能經過rabbitmqctl工具來建立。
複製代碼
/usr/sbin/rabbitmq-plugins enable rabbitmq_management
備註:若是發現命令執行完畢沒有打開此服務,15672端口沒有監聽,則是因爲沒有重啓mq致使的
http://localhost:4000/first-blog/rabbitmq.jpg
若是覆蓋了用戶須要使用如下命令修改mq用戶密碼 /usr/sbin/rabbitmqctl change_password 用戶名 密碼
rabbitmqctl stop_app
rabbitmqctl change_cluster_node_type dist
rabbitmqctl change_cluster_node_type ram
rabbitmqctl start_app
複製代碼
用時:3 分鐘
rabbitmqctl cluster_status
檢查集羣健康狀態,不正常節點從新加入集羣