rabbitmq相關

rabbitMQ說明文檔

rabbitMQ是什麼

RabbitMQ是由 LShift提供的一個 Advanced Message Queuing Protocol (AMQP)的開源實現,由以高性能、健壯以及可伸縮性出名的 Erlang寫成(因此也是繼承了這些優點)。

首先介紹AMQP和一些基本概念:

 當前各種應用大量使用異步消息模型,並隨之產生衆多消息中間件產品及協議,標準的不一致使應用與中間件之間的耦合限制產品的選擇,並增加維護成本。AMQP是一個提供統一消息服務的應用層標準協議,基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不同產品,不同開發語言等條件的限制。當然這種降低耦合的機制是基於與上層產品,語言無關的協議。AMQP協議是一種二進制協議,提供客戶端應用與消息中間件之間異步、安全、高效地交互。從整體來看,AMQP協議可劃分爲三層。

這種分層架構類似於OSI網絡協議,可替換各層實現而不影響與其它層的交互。AMQP定義了合適的服務器端域模型,用於規範服務器的行爲(AMQP服務器端可稱爲broker)

Model層決定這些基本域模型所產生的行爲,這種行爲在AMQP中用”command”表示,在後文中會着重來分析這些域模型。

Session層定義客戶端與broker之間的通信(通信雙方都是一個peer,可互稱做partner),爲command的可靠傳輸提供保障。

Transport層專注於數據傳送,並與Session保持交互,接受上層的數據,組裝成二進制流,傳送到receiver後再解析數據,交付給Session層。Session層需要Transport層完成網絡異常情況的彙報,順序傳送command等工作。

AMQP當中有四個概念非常重要:虛擬主機(virtual host),交換機(exchange),隊列(queue)和綁定(binding)。

虛擬主機(virtual host):一個虛擬主機持有一組交換機、隊列和綁定。爲什麼需要多個虛擬主機呢?RabbitMQ當中,用戶只能在虛擬主機的粒度進行權限控制。因此,如果需要禁止A組訪問B組的交換機/隊列/綁定,必須爲AB分別創建一個虛擬主機。每一個RabbitMQ服務器都有一個默認的虛擬主機“/”

隊列(Queue):由消費者建立的,是messages的終點,可以理解成裝消息的容器。消息一直存在隊列裏,直到有客戶端或者稱爲Consumer消費者連接到這個隊列並將message取走爲止。隊列可以有多個。

交換機(Exchange):可以理解成具有路由表的路由程序。每個消息都有一個路由鍵(routing key),就是一個簡單的字符串。交換機中有一系列的綁定(binding),即路由規則(routes)。交換機可以有多個。多個隊列可以和同一個交換機綁定,同時多個交換機也可以和同一個隊列綁定。(多對多的關係)

三種交換機:

1.  Fanout Exchange(不處理路由鍵):一個發送到交換機上的消息都會被轉發到與該交換機綁定的所有隊列上。Fanout交換機發消息是最快的。

2.  Direct Exchange(處理路由鍵):如果一個隊列綁定到該交換機上,並且當前要求路由鍵爲X,只有路由鍵是X的消息纔會被這個隊列轉發。

3.  Topic Exchange(將路由鍵和某模式進行匹配,可以理解成模糊處理):路由鍵的詞由“.”隔開,符號“#”表示匹配0個或多個詞,符號“*”表示匹配不多不少一個詞。因此audit.#能夠匹配到audit.irs.corporate,但是audit.*只會匹配到audit.irs

具體例子可以看下圖

持久化:隊列和交換機有一個創建時候指定的標誌durable,直譯叫做堅固的。durable的唯一含義就是具有這個標誌的隊列和交換機會在重啓之後重新建立,它不表示說在隊列當中的消息會在重啓後恢復。那麼如何才能做到不只是隊列和交換機,還有消息都是持久的呢?

但是首先一個問題是,你真的需要消息是持久的嗎?對於一個需要在重啓之後回覆的消息來說,它需要被寫入到磁盤上,而即使是最簡單的磁盤操作也是要消耗時間的。如果和消息的內容相比,你更看重的是消息處理的速度,那麼不要使用持久化的消息。

當你將消息發佈到交換機的時候,可以指定一個標誌“Delivery Mode”(投遞模式)。根據你使用的AMQP的庫不同,指定這個標誌的方法可能不太一樣。簡單的說,就是將 Delivery Mode設置成2,也就是持久的即可。一般的AMQP庫都是將Delivery Mode設置成1,也就是非持久的。所以要持久化消息的步驟如下:

1.  將交換機設成 durable

2.  將隊列設成 durable

3.  將消息的 Delivery Mode 設置成2

綁定(Bindings)如何持久化?我們無法在創建綁定的時候設置成durable。沒問題,如果綁定了一個 durable的隊列和一個durable的交換機,RabbitMQ會自動保留這個綁定。類似的,如果刪除了某個隊列或交換機(無論是不是 durable),依賴它的綁定都會自動刪除。

注意兩點:

1.  RabbitMQ不允許綁定一個非堅固(non-durable)的交換機和一個durable的隊列。反之亦然。要想成功必須隊列和交換機都是durable的。

2.  一旦創建了隊列和交換機,就不能修改其標誌了。例如,如果創建了一個non-durable的隊列,然後想把它改變成durable的,唯一的辦法就是刪除這個隊列然後重現創建。因此,最好仔細檢查創建的標誌。

消息隊列(MQ)使用過程

幾個概念說明:

1.  Broker:簡單來說就是消息隊列服務器實體。

2.  Exchange:消息交換機,它指定消息按什麼規則,路由到哪個隊列。

3.  Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。

4.  Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來。

5.  Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。

6.  vhost:虛擬主機,一個broker裏可以開設多個vhost,用作不同用戶的權限分離。

7.  producer:消息生產者,就是投遞消息的程序。

8.  consumer:消息消費者,就是接受消息的程序。

9.  channel:消息通道,在客戶端的每個連接裏,可建立多個channel,每個channel代表一個會話任務。

消息隊列的使用過程大概如下:

1.  客戶端連接到消息隊列服務器,打開一個channel。

2.  客戶端聲明一個exchange,並設置相關屬性。

3.  客戶端聲明一個queue,並設置相關屬性。

4.  客戶端使用routing key,在exchange和queue之間建立好綁定關係。

5.  客戶端投遞消息到exchange。

6.  exchange接收到消息後,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列裏。

rabbitMQ的優點(適用範圍)

1.        基於erlang語言開發具有高可用高併發的優點,適合集羣服務器。

2.        健壯、穩定、易用、跨平臺、支持多種語言、文檔齊全。

3.        有消息確認機制和持久化機制,可靠性高。

4.        開源

其他MQ的優勢:

1.        Apache ActiveMQ曝光率最高,但是可能會丟消息。

2.        ZeroMQ延遲很低、支持靈活拓撲,但是不支持消息持久化和崩潰恢復。

rabbitMQ單個節點部署文檔

Ubuntu(12.04)安裝rabbitMQ(python使用rabbitMQ服務)

1.   添加rabbitmq源:

1)   sudo vim /etc/apt/sources.list

2)   把 deb http://www.rabbitmq.com/debian/ testing main 添加進去

2.   添加公鑰:

1)   wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc

2)   sudo apt-key add rabbitmq-signing-key-public.asc

3.   更新並安裝rabbitmq-server:

1)   wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.2.2/rabbitmq-server_3.2.2-1_all.deb

2)   sudo dpkg -i rabbitmq-server_3.2.2-1_all.deb

4.   安裝pika:

1)   sudo apt-get install Python-pip

2)   sudo pip install pika

5.   配置文件:官方地址:http://www.rabbitmq.com/configure.html一般情況下,RabbitMQ的默認配置就足夠了。如果希望特殊設置的話,有兩個途徑:一個是環境變量的配置文件rabbitmq-env.conf;一個是配置信息的配置文件 rabbitmq.config;注意,這兩個文件默認是沒有的,如果需要必須自己創建。

1)   rabbitmq-env.conf:這個文件的位置是確定和不能改變的,位於:/etc/rabbitmq目錄下(這個目錄需要自己創建)。文件的內容包括了RabbitMQ的一些環境變量,常用的有:端口號、配置文件的路徑、需要使用的MNESIA數據庫的路徑、log的路徑插件的路徑。

具體的列表見:http://www.rabbitmq.com/configure.html#define-environment-variables

2)   rabbitmq.config:這是一個標準的erlang配置文件。它必須符合erlang配置文件的標準。它既有默認的目錄,也可以在rabbitmq-env.conf文件中配置。文件的內容詳見:http://www.rabbitmq.com/configure.html#config-items(更改完密碼配置除了重啓一定要再用命令行改一下)

安裝相關組件

1. rabbitmq-plugins:

a) sudo rabbitmq-plugins enable rabbitmq_management

b) sudo rabbitmqctl stop

c) sudo rabbitmq-server –detached

2. rabbitmqadmin:

a) wget http://hg.rabbitmq.com/rabbitmq-management/raw-file/rabbitmq_v3_2_1/bin/rabbitmqadmin

b) sudo cp rabbitmqadmin /usr/local/bin

c) cd /usr/local/bin

d) sudo chmod 777 rabbitmqadmin

自動安裝rabbitmq腳本

#!/bin/sh

echo "deb http://www.rabbitmq.com/debian/ testing main" >>/etc/apt/sources.list

wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc

sudo apt-key add rabbitmq-signing-key-public.asc

sudo apt-get update

sudo apt-get install rabbitmq-server

sudo rabbitmq-plugins enable rabbitmq_management

sudo rabbitmqctl stop

sleep 5

sudo rabbitmq-server -detached

wget http://hg.rabbitmq.com/rabbitmq-management/raw-file/rabbitmq_v3_2_1/bin/rabbitmqadmin

sudo cp rabbitmqadmin /usr/local/bin

sudo chmod 777 /usr/local/bin/rabbitmqadmin

rabbitMQ的管理(rabbitMQ常用命令文檔中會詳細說明)

1.   web界面

1)   rabbitmq-plugins enable rabbitmq_management

2)   invoke-rc.d rabbitmq-server stop

3)   invoke-rc.d rabbitmq-server start

4)   訪問http://localhost:15672,用戶名密碼都是guest

2.   Linux命令行

rabbitmqctl [-n node] [-q] {command} [command options...]

Command分類:

1)   Application Management

2)   Cluster Management

3)   User management

4)   Access control

5)   Parameter Management

6)   Policy Management

7)   Server Status

8)   Miscellaneous

詳見:https://www.rabbitmq.com/man/rabbitmqctl.1.man.html

rabbitMQ集羣配置

rabbitMQ是用erlang開發的,集羣非常方便,因爲erlang天生就是一門分佈式語言,但其本身並不支持負載均衡。

rabbit模式大概分爲以下三種:

單一模式:最簡單的情況,非集羣模式。沒什麼好說的。

普通模式:默認的集羣模式。對於Queue來說,消息實體只存在於其中一個節點,A、B兩個節點僅有相同的元數據,即隊列結構。當消息進入A節點的Queue中後,consumer從B節點拉取時,rabbitMQ會臨時在A、B間進行消息傳輸,把A中的消息實體取出並經過B發送給consumer。所以consumer應儘量連接每一個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點建立物理Queue。否則無論consumer連A或B,出口總在A,會產生瓶頸。該模式存在一個問題就是當A節點故障後,B節點無法取到A節點中還未消費的消息實體。如果做了消息持久化,那麼得等A節點恢復,然後纔可被消費;如果沒有持久化的話,然後就沒有然後了……

鏡像模式:把需要的隊列做成鏡像隊列,存在於多個節點,屬於rabbitMQ的HA方案。該模式解決了上述問題,其實質和普通模式不同之處在於,消息實體會主動在鏡像節點間同步,而不是在consumer取數據時臨時拉取。該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,集羣內部的網絡帶寬將會被這種同步通訊大大消耗掉。所以在對可靠性要求較高的場合中適用(後面會詳細介紹這種模式,目前我們搭建的環境屬於該模式)瞭解集羣中的基本概念:rabbitMQ的集羣節點包括內存節點、磁盤節點。顧名思義內存節點就是將所有數據放在內存,磁盤節點將數據放在磁盤。不過,如前文所述,如果在投遞消息時,打開了消息的持久化,那麼即使是內存節點,數據還是安全的放在磁盤。一個rabbitMQ集 羣中可以共享 user,vhost,queue,exchange等,所有的數據和狀態都是必須在所有節點上覆制的,一個例外是,那些當前只屬於創建它的節點的消息隊列,儘管它們可見且可被所有節點讀取。rabbitMQ節點可以動態的加入到集羣中,一個節點它可以加入到集羣中,也可以從集羣環集羣會進行一個基本的負載均衡。

集羣中有兩種節點:

內存節點:只保存狀態到內存(一個例外的情況是:持久的queue的持久內容將被保存到disk)

磁盤節點:保存狀態到內存和磁盤。內存節點雖然不寫入磁盤,但是它執行比磁盤節點要好。集羣中,只需要一個磁盤節點來保存狀態 就足夠了 如果集羣中只有內存節點,那麼不能停止它們,否則所有的狀態,消息等都會丟失。

集羣配置

我們這邊有兩臺服務器,hostname分別爲:rabbit1(192.168.8.35)、rabbit3(192.168.8.34)。

配置步驟如下:

1.   rabbit1和rabbit3做爲rabbitMQ集羣節點,分別安裝rabbitMQ-Server ,安裝後分別啓動rabbitMQ-server

2.   在安裝好的兩臺節點服務器中,分別修改/etc/hosts文件,指定rabbit1和rabbit3的hosts:192.168.8.35 rabbit1 192.168.8.34 rabbit3

3.   還有hostname文件也要正確,分別是rabbit1和rabbit3,如果修改hostname建議安裝rabbitMQ前修改。請注意rabbitMQ集羣節點必須在同一個網段裏,如果是跨廣域網效果就差。

修改hostname的方法:

a)   啓用root用戶

運行命令 sudo passwd root 爲root用戶設置密碼

b)   以root用戶身份登錄

c)   編輯文件/etc/hosts 將下面的一行

127.0.1.1  xxxxx

替換爲

127.0.1.1  newhostname

d)   編輯 /etc/hostname文件 刪除該文件的所有內容,添加newhostname

e)   運行一下命令 hostname newhostname

f)   退出root用戶 改用一般用戶登錄即可

4.   設置每個節點Cookie:rabbitMQ的集羣是依賴於erlang的集羣來工作的,所以必須先構建起erlang的集羣環境。Erlang的集羣中各節點是通過一個magic cookie來實現的,這個cookie存放在 /var/lib/rabbitMQ/.erlang.cookie 中,文件是400的權限。所以必須保證各節點cookie保持一致,否則節點之間就無法通信。將其中一臺節點上的.erlang.cookie值複製下來保存到其他節點上,要注意文件的權限和屬主屬組。先修改下.erlang.cookie權限:

#chmod 777  /var/lib/rabbitMQ/.erlang.cookie

複製完後重啓下rabbitMQ。

複製好後別忘記還原.erlang.cookie的權限,否則可能會遇到錯誤:

#chmod 400 /var/lib/rabbitMQ/.erlang.cookie

設置好cookie後先將三個節點的rabbitMQ重啓:

# rabbitmqctl stop

# rabbitMQ-server start

5.   停止所有節點rabbitMQ服務,然後使用detached參數獨立運行,這步很關鍵,尤其增加節點停止節點後再次啓動遇到無法啓動都可以參照這個順序:

rabbit@rabbit3# rabbitmqctl stop

rabbit@rabbit3# rabbitMQ-server –detached

6.   將rabbit1和rabbit3連接起來,執行如下命令:

rabbit@rabbit3# rabbitmqctl stop_app

rabbit@rabbit3# rabbitmqctl reset

rabbit@rabbit3# rabbitmqctl cluster rabbit@rabbit3 rabbit@rabbit1   

rabbit@rabbit3# rabbitmqctl start_app

7.   在rabbit1和rabbit3上,運行cluster_status命令查看集羣狀態:

rabbit@rabbit3# rabbitmqctl cluster_status

Cluster status of node rabbit@rabbit1 ...

[{nodes,[{disc,[rabbit@rabbit3,rabbit@rabbit1]}]},

{running_nodes,[rabbit@rabbit3,rabbit@rabbit1]}]

...done.這時我們可以看到每個節點的集羣信息,分別有兩個磁盤節點。

這樣rabbitMQ集羣就正常工作了,這種模式更適合非持久化隊列,只有該隊列是非持久的,客戶端才能重新連接到集羣裏的其他節點,並重新創建隊列。假如該隊列是持久化的,那麼唯一辦法是將故障節點恢復起來。

爲什麼rabbitMQ不將隊列複製到集羣裏每個節點呢?這與它的集羣的設計本意相沖突,集羣的設計目的就是增加更多節點時,能線性的增加性能(CPU、內存)和容量(內存、磁盤)。理由如下:

1. storage space: If every cluster node had a full copy of every queue, adding nodes wouldn’t give you more storage capacity. For example, if one node could store 1GB of messages, adding two more nodes would simply give you two more copies of the same 1GB of messages.

2. performance: Publishing messages would require replicating those messages to every cluster node. For durable messages that would require triggering disk activity on all nodes for every message. Your network and disk load would increase every time you added a node, keeping the performance of the cluster the same (or possibly worse).

rabbitMQ Highly Available Queue

如果你 的 rabbitMQ broker 只是由單獨一個 node 構成,那麼該 node 的失效將導致整個服務臨時性的不可用,並且可能會導致 message 丟失(尤其是在非持久化 message 存儲於非持久化的 queue 中的時候)。你當然可以將所有 publish 的 message 都設置爲持久化的,並且使用持久化的 queue ,但是你仍然無法避免 由於 buffering 導致的問題:因爲在 message 被髮出後和被 寫入磁盤並 fsync 之間存在一個雖然短暫但是會產生問題的時間窗。通過 [publisher confirms] 機制能夠確保客戶端知道哪些消息已經寫入磁盤,儘管如此,你一定仍不希望遇到因爲單點故障導致的服務器停用,進而導致服務不可用的尷尬局面,同樣,你也一定不喜歡將每一條 message 都寫入磁盤導致的服務器性能退化。

你可以使用 rabbitMQ node 構成的cluster 來構建屬於你的 rabbitMQ broker 。如此做,從服務的整體可用性上來講,該 cluster 對於單獨 node 的失效是具有彈性的,但是同時存在一些需要重點注意的點:儘管exchange和binding能夠在單點失效的問題上倖免於難,但是 queue 和其上持有的 messgage 卻不行。這是 因爲 queue 及其內容僅僅貯存於單個 node 之上,所以一個 node 的失效將表現爲其對應的 queue 的不可用。

你可以使用 [ active/passive] 形式的 node 對,一旦 active node 失效了,passive node 將會啓用並從失效 node 處接管工作。這種方式甚至可以同 cluster 應用結合起來使用。儘管該方式可以確保對失效問題的快速檢測和恢復,但是仍然會 存在問題:如 passive node 會花費很長時間才能完全啓動起來或者甚至根本啓動不起來。這在最壞情況下會導致存在於失效 node 上的 queue 的臨時不可用狀態。

爲了解決上述各種問題,我們開發了 active/active HA queue 。從原理上講,是 採用將 queue 鏡像到 cluster 中的其他 node 上的方式實現的。 在該實現下,如果 cluster 中的一個 node 失效了,queue 能夠自動地切換到鏡像 queue 中的一個繼續工作以保證服務的可用性。該解決方案仍然要求使用 rabbitMQ cluster ,這也意味着其無法在 cluster 內無縫地處理 network partition 問題。因此,不推薦跨 WAN 使用(雖然如此,客戶端當然可以從遠端或者近端進行連接)。

Mirrored Queue Behaviour

在通常的用法中,針對每一個mirrored-queue都包含一個 master和多個slave,分別對應於不同的node。slave會準確地按照master 執行命令的順序進行命令執行,故slave與master上維護的狀態應該是相同的。除publish外的所有動作都只會向master發送,然後再由 master將命令執行的結果廣播給 slave 們,故看似從mirrored queue 中 consuming 的客戶端實際上是從 master 上進行的 consuming 。

如果某個 slave 失效了,系統除了做些許記錄外幾乎啥都不做:master 仍舊是 master ,客戶端不需要採取任何行動,或者被通知 slave 的失效。

如果 master 失效了,那麼 slave 中的一個必須被提升爲 master ,在這種情況下,將發生下面的事情:

某一個 slave 會被提升爲新的 master 。被 選中作爲新的 master 的 slave 通常是看哪個 slave 最老(這個也論資排輩!~),因爲最老的 slave 與前任 master 之間的同步狀態應該是最好的(估計一起吃過不少飯喝過不少酒)。然而,需要注意的是,如果存在沒有任何一個 slave 與 master 進行過 [ synchronised]的情況(新官上任沒幹多就 master 就掛了),那麼前任 master “私有的” message 將會丟失。

slave 會認爲所有之前有聯繫的 consumer 都被突然地(粗魯地)斷開了。在 這種情況下,slave (根據上下文補充翻譯:被提升爲 master 的那個傢伙)會 requeue 所有已經投遞給客戶端但尚未收到 acknowledgement 的 message 。這類 message 中將包括那些客戶端已發送過 acknowledgement 進行確認的消息:或者因爲 acknowledgement 抵達 master 之前其丟失了,或者因爲 acknowledgement 在 master 向 slave 進行廣播的時候丟失了。無論是上述哪種情況,新 master 除了將其認爲尚未 acknowledged 的消息進行 requeue 外沒有更好的處理辦法。

從 mirrored-queue 處 consume 消息的客戶端如果支持我們提供的 [ Consumer Cancellation Notifications ]機制,將可以收到關於他們對 mirrored-queue 的訂閱被突然地(粗魯地)取消掉的通知。在 這種情況下,他們應該對 queue 執行 re-consume ,此時將會從新任 master 處獲取消息。發送該通知的原因是:通知客戶端“master 已經失效”這個結果是必要的;否則客戶端可能繼續對之前過時的、已經失效的前任 master 發送確認消息,並期望能夠再次從前任 master 處收 message (此處爲本人按照自己的理解進行解讀),然後之後的 message 將是從新的 master 處發來。可以確定的是,連接到失效 node 上的客戶端將會發現之前的連接已經斷開,之後會重新連接到 cluster 中的其他存活的 node 上。

作爲 requeue 的結果,從 queue 中 re-consume 的客戶端必須意識到自己非常可能在隨後的交互過程中收到自己之前已經收到過的消息。

一旦完成了選中的 slave 被提 升成 master 的動作,發送到 mirrored-queue 的所有 message 將不會再丟失:publish 到 mirrored-queue 的所有消息總是被直接 publish 到 master 和所有的 slave 上。這樣一旦 master 失效了,message 仍然可以繼續發送到其他 slave 上,並且在新 slave 被提升爲 master 之後,將這些 message 添加到(該 master 所在的) queue 中。

同樣地, 如果客戶端使用了 [ publisher confirm ] 機制,即使“在 message 被 publish 後和 message 被確認前”的期間,出現 master(或者任何 slave)失效的情況,其所 publish 的 message 仍舊可以被正確無誤地確認。故從 publisher 的角度來看,將消息 publish 到 mirrored-queue 與 publish 到任何種類的 queue 中沒有任何差別。只有 consumer 需要意識到當收到 [ Consumer Cancellation Notification] 時,自己可能需要再次從 mirrored-queue 中 re-consume 。

如果你使用 noAck=true 屬性從 mirrored-queue 中 consume message(即客戶端不發送 message 確認),則消息存在丟失的可能。這個和標準情形沒有任何差別: broker 認爲 message 一旦向具有 noAck=true 屬性的 consumer 執行了發送行爲,broker 就認爲該消息已經被確認了。此 時如果客戶端突然地斷開了,message 將會丟失(假設客戶端此時尚未收到該 message)。在採用 mirrored-queue 的情況下,如果 master 失效了,那些仍處於發送給具有 noAck=true 屬性的 consumer 路上的 message 將不會被這些客戶端接收到,並且不會被新任 master 執行 requeue 操作。因爲有可能處於 consuming 狀態的客戶端是與存活着的 node 連接着的,此時可以採用 [Consumer Cancellation Notification] 機制在此類事件發生時用於進行相關處理。當然,在實際中,如果你比較關心丟失 message 的問題,則建議你在 consume 時使用 noAck=false 。

Publisher Confirms and Transactions

Mirrored queue 同時支持 [Publisher Confirm] 和 [Transaction] 兩種機制。在兩種機制中進行選擇的依據是,其在 queue 的全部鏡像中產生波及的範圍。在 Transaction 機制中,只有在當前事務在全部鏡像 queue 中執行後,客戶端纔會在收到 tx.commit-ok 消息。同樣地,在 publisher confirm 機制中,向 publisher 進行當前 message 確認的前提是該 message 被全部鏡像所 accept 了。你可以按照如下語義對上述機制進行理解:即 message 被路由到多個普通的 queue 中,更進一步,在帶有 publish 的事務中也同樣會路由到多個 queue 中。

Unsynchronised Slaves

一個 node 可以在任意時刻加入到一個 cluster 中。 按照 queue 的自身配置信息,當一個 node 加入到一個 cluster 中時,可能將當前 node 設置成 slave 。如果是這樣,新增 slave 上(的 queue)將會是空的:其不會包含任何當前(cluster 中) queue 上業已存在的內容,且當前也沒有任何同步協議可用。新增 slave 將可以收到 publish 到其對應 queue 的新 message ,並且在一定的運行時間後,(其 queue 中的內容)將可以準確呈現(當前 cluster 中的) mirrored-queue 的尾部 message 的“面貌”。隨着(當前 cluster 中) mirrored-queue 上的 message 被逐漸 consume ,新增 slave 之前“錯失”的 message 數量(以 queue 頭上的 size 表示 - 即 message 的多少)將會逐步縮減,直到 slave 的內容與 master 的內容 最終完全變成一致。此時,我們可以認爲 slave 已經處於完全同步狀態了,需要注意的是,上述同步行爲的產生是基於客戶端的動作觸發,即其會逐步消耗光 queue 中業已存在的 message 。

故新增 slave 並沒有爲提高 queue 內容的冗餘性或可用性提供額外的好處,只有在新增 slave 前,就已將存在於 queue 中的內容移除的情況下才能產生確實的好處。鑑於這個原因,推薦你最好在創建 mirrored queue 前先設置相應的 node 爲 slave ,或者更進一步,你可以確保你進行 message 相關操作時,只會導致產生“存活期非常短或者空的 queue”,因爲這種 queue 中的 message 會很快被 consume 光。

你可以通過如下 rabbitMQctl 命令或者管理插件來確定哪些 slave 已經進行了同步:

1

rabbitMQctl list_queues name slave_pids synchronised_slave_pids

Starting and Stopping Nodes

啓動和停止 node

如果你停止了 mirrored-queue 中具有 master 行爲的 rabbitMQ node ,那麼將會發生某個作爲 slave 的 node 被提升爲 master 的情況(假定確實存在一個這樣的 slave)。如果你繼續停止(具有 master 行爲的)node ,你最終會面臨 mirrored-queue 中沒有任何 slave 的情況:即只存在一個 node ,且其爲 master 。 在 mirrored-queue 被聲明爲持久的情況下,如果其所包含的最後一個可用 node( 需要注意:此時該 node 已經成爲了 master)被停止,那麼位於該 queue 中的持久化 message 將在該 node 重啓後得到恢復。通常來說, 當你重啓一些 node - 如果這些 node 當初 mirrored-queue 的一部分 - 那麼這些 node 將會在重啓後重新加入到該 mirrored-queue 中。

然而, 當前沒有任何方式可以讓重新加入到 mirrored-queue 中的 slave 確認是否自身擁有的 queue 的內容與 master 的不同(例 如,可能出現在 network partition 的情況中)。所以,當一個 slave 重新加入到 mirrored-queue 中時,它將果斷拋棄任何自身之前擁有的本地的持久化內容,並以空( queue )的狀態啓動。該 slave 的行爲從某種意義上來說像是一個新加入到 cluster 中的 node 。

Configuring Mirroring

queue 可以通過[ policy]對鏡像功能進行控制。任何時候策略都是可以改變的;你可以首先創建一個 non-mirrored queue ,然後在之後的某一個時候將其再變成鏡像的(或者相反操作)。在  non-mirrored queue 和不包含任何 slave 的鏡像 queue 之間存在一點差別 - 前者因爲不需要使用 額外 支持鏡像功能的基礎組件,故可以運行的更快。

(相對來講)你更應該關注爲 queue 添加鏡像的行爲。

用兩臺機器建立鏡像隊列解決HA問題

前提

1.         兩臺機器已經建立rabbitMQ集羣。

2.         rabbitmq-plugins 和 rabbitmqadmin安裝正常。

3.         /etc/hosts文件,在我們的服務器上,兩臺機器的IP是192.168.8.34和192.168.8.35,hosts如下:

127.0.0.1localhost

127.0.1.1rabbit3

192.168.8.11  ubuntu

192.168.8.35  rabbit1

127.0.0.1       localhost

127.0.1.1       rabbit1

192.168.8.11    ubuntu

192.168.8.34    rabbit3

ha-mode

ha-params

Result

all

(absent)

Queue is mirrored across all nodes in the cluster. When a new node is added to the cluster, the queue will be mirrored to that node.

exactly

count

Queue is mirrored to count nodes in the cluster. If there are less than count nodes in the cluster, the queue is mirrored to all nodes. If there are more than countnodes in the cluster, and a node containing a mirror goes down, then a new mirror will not be created on another node. (This is to prevent queues migrating across a cluster as it is brought down.)

nodes

node names

Queue is mirrored to the nodes listed in node names. If any of those node names are not a part of the cluster, this does not constitute an error. If none of the nodes in the list are online at the time when the queue is declared then the queue will be created on the node that the declaring client is connected to.

通過set_policy來建立鏡像隊列

Some examples

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

所有ha.開頭的隊列自動成爲鏡像隊列,每個節點都會有這個隊列。

一些測試

1.         聲明一個policy,以ha.開頭的隊列自動成爲鏡像隊列:

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

2.         在rabbit3節點上建立一個名字爲ha.123的隊列,durable設爲true:

sudo rabbitmqadmin declare queue name=ha.123 durable=true

3.         在rabbit3節點上建立一個名字爲aaaaaa的隊列,durable設爲true:

sudo rabbitmqadmin declare queue name=aaaaaa durable=true

4.         查看rabbit1節點的queues:

test@rabbit1:~$ sudo rabbitmqctl list_queues

Listing queues ...

aaaaaa  0

ha.123  0

5.         停止rabbit3:

sudo rabbitmqctl stop_app

6.         再次查看rabbit1節點的queues:

test@rabbit1:~$ sudo rabbitmqctl list_queues

Listing queues ...

ha.123  0

由上面這個小測試可以發現,ha.123保留了,而aaaaaa沒有保留,這就說明了policy生效了,符合policy的ha.123自動建立了鏡像隊列,所以即使rabbit1關掉了服務,ha.123依舊在其他節點存在着,這樣就保證了HA。

rabbitMQ一些常用命令

rabbitctl

rabbitmqctl 是rabbitMQ中間件的一個命令行管理工具。它通過連接一箇中間件節點執行所有的動作。

rabbitmqctl [-n node] [-q] {command} [command options…]

[-n node]

默認的節點是”rabbit@server”,一般是本地節點。

rabbitmqctl 默認產生詳細輸出。通過”-q”標示可選擇安靜模式。

應用和集羣管理

1.  停止rabbitMQ應用,關閉節點 : rabbitmqctl stop

2.  停止rabbitMQ應用 : rabbitmqctl stop_app

3.  啓動rabbitMQ應用 : rabbitmqctl start_app

4.  顯示rabbitMQ中間件各種信息 : rabbitmqctl status

5.  重置rabbitMQ節點 : rabbitmqctl reset和  rabbitmqctl force_reset 從它屬於的任何集羣中移除,從管理數據庫中移除所有數據,例如配置過的用戶和虛擬宿主, 刪除所有持久化的消息。 force_reset命令和reset的區別是無條件重置節點,不管當前管理數據庫狀態以及集羣的配置。如果數據庫或者集羣配置發生錯誤才使用這個最後 的手段。 注意:只有在停止rabbitMQ應用後,reset和force_reset才能成功。

6.  循環日誌文件 : rabbitmqctl rotate_logs[suffix]

7.  加入到某個節點中:rabbitmqctl join_cluster {clusternode} [--ram]默認是ram類型的,也可以是disc類型

8.  集羣目前的狀態:rabbitmqctl cluster_status

9.  改變當前節點的類型:rabbitmqctl change_cluster_node_type {disc | ram}使用這個命令的時候必須先把該節點stop。

10. 同步某個隊列(建立鏡像隊列):rabbitmqctl sync_queue {queue-name}

11. 取消同步某個隊列:rabbitmqctl cancel_sync_queue{queue-name}

用戶管理

1.  添加用戶:rabbitmqctl add_user username password

2.  刪除用戶:rabbitmqctl delete_user username

3.  修改密碼:rabbitmqctl change_password username newpassword

4.  清除密碼:rabbitmqctl clear_password {username}

5.  設置用戶標籤:rabbitmqctl set_user_tags {username} {tag…}如果tag爲空則表示清除這個用戶的所有標籤

6.  列出所有用戶 :rabbitmqctl list_users

權限控制

1.  創建虛擬主機:rabbitmqctl add_vhost vhostpath

2.  刪除虛擬主機:rabbitmqctl delete_vhost vhostpath

3.  列出所有虛擬主機:rabbitmqctl list_vhosts

4.  設置用戶權限:rabbitmqctl set_permissions [-p vhostpath] {username} {conf} {write} {read}

5.  清除用戶權限:rabbitmqctl clear_permissions [-p vhostpath] {username}

6.  列出虛擬主機上的所有權限:rabbitmqctl list_permissions [-p vhostpath]

7.  列出用戶權限:rabbitmqctl list_user_permissions {username}

參數管理

這個不常用,具體的可以去官網看文檔

協議管理

1.  設置協議:rabbitmqctl set_policy [-p vhostpath] [--priority priority] [--apply-to apply-to] {name} {pattern} {definition}

a)  name

協議的名字

b)  pattern

匹配的正則表達式

c)  definition

json term的形式來定義這個協議

d)  priority

優先級,數字越大優先級越高,默認爲0

e)  apply-to

policy的類型,有三種:queues exchanges all 默認爲all,具體定義可以去官網看文檔

2.  清除協議:rabbitmqctl clear_policy [-p vhostpath] {name}

3.  列出協議列表:rabbitmqctl list_policies [-p vhostpath]

服務器狀態

1.  隊列列表:rabbitmqctl list_queues [-p vhostpath] [queueinfoitem…]

queueinfoitem:

a)  name

b)  durable

c)  auto_delete

d)  arguments

e)  policy

f)  pid

g)  owner_pid

h)  exclusive_consumer_pid

i)  exclusive_consumer_tag

j)  messages_ready

k)  messages_unacknowledged

l)  messages

m)  consumers

n)  active_consumers

o)  memory

p)  slave_pids

q)  synchronized_slave_pids

r)  status

2.  交換機列表:rabbitmqctl list_exchanges [-p vhostpath] [exchangeinfoitem…]

exchangeinfoitem:

a)  name

b)  type

c)  durable

d)  auto_delete

e)  internal

f)  arguments

g)  policy

3.  綁定列表:rabbitmqctl list_bindings [-p vhostpath] [bindinginfoitem…]

bindinginfoitem:

a)  source_name

b)  source_kind

c)  destination_name

d)  destination_kind

e)  routing_key

f)  arguments

4.  連接列表:rabbitmqctl list_connections不常用,具體去官網看文檔

5.  通道列表:rabbitmqctl list_channels不常用,具體去官網看文檔

6.  消費者列表:rabbitmqctl list_consumers

7.  當前狀態:rabbitmqctl status

8.  當前環境:rabbitmqctl environment

9.  相關報告:rabbitmqctl report

一些其他的命令

後臺開啓rabbitmq服務:rabbitmq-server –detached

聲明隊列:rabbitmqadmin declare queue name=queue-name durable={false | true}

發佈消息:rabbitmqadmin publish exchange=exchange-name routing_key=key payload=”context”

如果有任何疑問可以去官網看文檔:

https://www.rabbitmq.com/man/rabbitmqctl.1.man.html

OpenStack中rabbitMQ的使用

Nova各個模塊直接基於AMQP實現通信

經過一番調研,發現OpenStack之中,與rabbitMQ直接相關聯的模塊是NOVA模塊,NOVA中的每個組件可能是一個消息的發送者(如API、Scheduler),也可能是一個消息的接受者(如compute、volume、network)。Nova各個模塊之間基於AMQP消息實現通信,但是真正實現消息調用的應用流程主要是RPC機制。Nova基於RabbitMQ實現兩種RPC調用:RPC.CALL和RPC.CAST,其中RPC.CALL基於請求與響應方式,RPC.CAST只是提供單向請求,兩種RPC調用方式在Nova中均有不同的應用場景。

在Nova中主要實現Direct和Topic兩種交換器的應用,在系統初始化的過程中,各個模塊基於Direct交換器針對每一條系統消息自動生成多個隊列注入RabbitMQ服務器中,依據Direct交換器的特性要求,Binding Key=“MSG-ID”的消息隊列只會存儲與轉發Routing Key=“MSG-ID”的消息。同時,各個模塊作爲消息消費者基於Topic交換器自動生成兩個隊列注入RabbitMQ服務器中。

Nova的各個模塊在邏輯功能是可以劃分爲兩種:Invoker和Worker,其中Invoker模塊主要功能是向消息隊列中發送系統請求消息,如Nova-API和Nova-Scheduler;Worker模塊則從消息隊列中獲取Invoker模塊發送的系統請求消息以及向Invoker模塊回覆系統響應消息,如Nova-Compute、Nova-Volume和Nova-Network。Invoker通過RPC.CALL和RPC.CAST兩個進程發送系統請求消息;Worker從消息隊列中接收消息,並對RPC.CALL做出響應。Invoker、Worker與RabbitMQ中不同類型的交換器和隊列之間的通信關係如圖所示。

  Nova根據Invoker和Worker之間的通信關係可邏輯劃分爲兩個交換域:Topic交換域與Direct交換域,兩個交換域之間並不是嚴格割裂,在信息通信的流程上是深度嵌入的關係。Topic交換域中的Topic消息生產者(Nova-API或者Nova-Scheduler)與Topic交換器生成邏輯連接,通過PRC.CALL或者RPC.CAST進程將系統請求消息發往Topic交換器。Topic交換器根據系統請求消息的Routing Key分別送入不同的消息隊列進行轉發,如果消息的Routing Key=“NODE-TYPE.NODE-ID”,則將被轉發至點對點消息隊列;如果消息的Routing Key=“NODE-TYPE”,則將被轉發至共享消息隊列。Topic消息消費者探測到新消息已進入響應隊列,立即從隊列中接收消息並調用執行系統消息所請求的應用程序。每一個Worker都具有兩個Topic消息消費者程序,對應點對點消息隊列和共享消息隊列,鏈接點對點消息隊列的Topic消息消費者應用程序接收RPC.CALL的遠程調用請求,並在執行相關計算任務之後將結果以系統響應消息的方式通過Direct交換器反饋給Direct消息消費者;同時鏈接共享消息隊列的Topic消息消費者應用程序只是接收RPC.CAST的遠程調用請求來執行相關的計算任務,並沒有響應消息反饋。因此,Direct交換域並不是獨立運作,而是受限於Topic交換域中RPC.CALL的遠程調用流程與結果,每一個RPC.CALL激活一次Direct消息交換的運作,針對每一條系統響應消息會生成一組相應的消息隊列與交換器組合。因此,對於規模化的OpenStack雲平臺系統來講,Direct交換域會因大量的消息處理而形成整個系統的性能瓶頸點。

系統RPC.CALL以及RPC.CAST調用流程

  由前文可以看出,RPC.CALL是一種雙向通信流程,即Worker程序接收消息生產者生成的系統請求消息,消息消費者經過處理之後將系統相應結果反饋給Invoker程序。例如,一個用戶通過外部系統將“啓動虛擬機”的需求發送給NOVA-API,此時NOVA-API作爲消息生產者,將該消息包裝爲AMQP信息以RPC.CALL方式通過Topic交換器轉發至點對點消息隊列,此時,Nova-Compute作爲消息消費者,接收該信息並通過底層虛擬化軟件執行相應虛擬機的啓動進程;待用戶虛擬機成功啓動之後,Nova-Compute作爲消息生產者通過Direct交換器和響應的消息隊列將“虛擬機啓動成功”響應消息反饋給Nova-API,此時Nova-API作爲消息消費者接收該消息並通知用戶虛擬機啓動成功,一次完整的虛擬機啓動的RPC.CALL調用流程結束。其具體流程如圖所示:

  (1)Invoker端生成一個Topic消息生產者和一個Direct消息消費者。其中,Topic消息生產者發送系統請求消息到Topic交換器;Direct消息消費者等待響應消息。

  (2)Topic交換器根據消息的Routing Key轉發消息,Topic消費者從相應的消息隊列中接收消息,並傳遞給負責執行相關任務的Worker。

  (3)Worker根據請求消息執行完任務之後,分配一個Direct消息生產者,Direct消息生產者將響應消息發送到Direct交換器。

  (4)Direct交換器根據響應消息的Routing Key轉發至相應的消息隊列,Direct消費者接收並把它傳遞給Invoker。

  RPC.CAST的遠程調用流程與RPC.CALL類似,只是缺少了系統消息響應流程。一個Topic消息生產者發送系統請求消息到Topic交換器,Topic交換器根據消息的Routing Key將消息轉發至共享消息隊列,與共享消息隊列相連的所有Topic消費者接收該系統請求消息,並把它傳遞給響應的Worker進行處理,其調用流程如圖所示:

自動創建的exchange和queue

主機名爲hostname,openstack各個組件啓動後:

Exchanges

1.      nova (topic exchange)

Queues

1.      compute. hostname

2.      compute

3.      network. hostname

4.      network

5.      volume. hostname

6.      volume

7.      scheduler. hostname

8.      scheduler

9.      ce

rabbitMQ測試

硬件環境

INTEL 四核2.13主頻

5506*2

300G*6 3.5寸 SAS 15K (1.8TB)

8G

RAID 0 1

DVD

2*1000M網卡

冗餘電源570W

原廠3年服務

軟件環境

OS:Linux version 3.2.0-29-generic

rabbitMQ:3.2.1

功能測試

Nova工作狀態:正常

Cinder工作狀態:正常

Ceilmoter工作狀態:正常

Glance工作狀態:

Network工作狀態:

非功能測試

可用性測試

在rabbitMQ可承受的最大壓力(32連接,發送10W個大小爲4KB的消息)下進行測試(鏡像):

1.    發送消息的時候暴力停掉master節點,然後將消息傳遞切換到slave節點上,觀察服務器是否能正常運行、消息是否有丟失。再恢復掛掉的舊master節點,觀察是否能再同步到一致的狀態。

32連接發送1W個4KB的消息,發送過程中突然停掉master,此時slave節點的鏡像隊列上有131679個消息。再給slave傳遞消息。最終slave有451679個消息,此時恢復之前的master,經過查詢發現該隊列依舊有451679個消息,消息沒有丟失。

2.    發送消息的時候暴力停掉slave節點,觀察服務器是否能正常運行、消息是否有丟失。再恢復掛掉的slave節點,觀察是否能再同步到一致的狀態。

經過測試,恢復的slave節點狀態最終和master一致。

3.    給mater的節點發送消息時暴力停掉master節點,刪除相關數據(模擬磁盤損壞),再切換到給slave節點發消息,發送完畢之後,重啓mater節點,觀察是否能同步一致,是否有消息丟失。

經過測試,停掉master、清除相關數據之後,slave節點還有87900個消息,將清楚過數據的master重新和slave建立集羣,經過同步後slave和mater都有87900個消息,沒有丟失。

4.    發送消息時暴力停掉slave節點,刪除相關數據(模擬磁盤損壞),消息發送完畢之後,重啓slave節點,觀察是否能同步一致,是否有消息丟失。

經過測試,slave節點重新加入集羣后,和master同步一致,沒有丟失消息。

5.    模擬斷網,stop networking,使得兩臺直接無法互聯,輸入cluster_status指令,觀察各個節點是否能檢測到已經斷網。

將rabbit1的networking stop之後,在rabbit2上查看cluster_status,發現rabbit2在running,rabbit1 down掉了。能檢測到是否已經斷網。

擴展性測試

  由於rabbitMQ自帶集羣功能,擴展性很好,只要再往裏面加入節點就可以實現擴展。

性能測試

單點單連接的性能極限:

測試單連接發送1KB消息、32KB消息、64KB消息、128KB消息...的速度,直到無法發送消息或者性能有明顯下降爲止。每次測試要先purge清空隊列。

單點多連接的性能極限:

用分別用32、64、128...個連接發送1KB、32KB、64KB...的消息,直到無法發送消息或者性能有明顯下降爲止。每次測試要先purge清空隊列。



集羣單連接的性能極限(鏡像):

測試單連接發送1KB消息、32KB消息、64KB消息、128KB消息...的速度,直到無法發送消息或者性能有明顯下降爲止。每次測試要先purge清空隊列。

集羣多連接的性能極限(鏡像):

用分別用32、64、128...個連接發送1KB、32KB、64KB...的消息,直到無法發送消息或者性能有明顯下降爲止。每次測試要先purge清空隊列。

發送速度|CPU使用率|內存佔用

1KB

32KB

64KB

128KB

單連接(每個連接100000個消息)

313|5%-6%|1.2%

234|6%|3%

186|7%-8%| 3.6%

133|6%-8%|19%

32個連接(每個連接10000個消息)

9900|110%-144%| 2.3%

7300-7500|190%-210%| 32%

5800|190%-230%|被強行停掉了因爲內存超過閾值了(60%)

4200|260%-270%|強行被停掉了因爲內存超過了閾值(60%)

64個連接(每個連接10000個消息)

20000|308%-320%|3.8%

15000|338%-348%|被強行停掉了因爲內存超過了閾值(60%)

9000|348%-355%|被強行停掉了因爲內存超過了閾值(60%)

5000-6000|355%370%| 被強行停掉了因爲內存超過了閾值(60%)

128個連接(每個連接10000個消息)

26000-35000|255%-255%| 被強行停掉了因爲內存超過了閾值(60%)

5000-13000|107%-255% | 被強行停掉了因爲內存超過了閾值(60%)

900-7500|30%-314%  | 被強行停掉了因爲內存超過了閾值(60%)

0-4000|60%-355%  | 被強行停掉了因爲內存超過了閾值(60%)

集羣單連接(鏡像)(每個連接100000個消息)

313|13%-17%| 1.1%

233|16%-19%|10.8%

187|17%-20% |20.4%

133|19%-22%| 35.7%

集羣32個連接(鏡像)(每個連接10000個消息)



10000|270%-304%|2.2%

很不穩定、被強行停掉了

很不穩定、被強行停掉了

很不穩定、被強行停掉了

集羣64個連接(鏡像)(每個連接10000個消息)



很不穩定、被強行停掉了

很不穩定、被強行停掉了

很不穩定、被強行停掉了

很不穩定、被強行停掉了

集羣128個連接(鏡像)(每個連接10000個消息)



很不穩定、被強行停掉了

很不穩定、被強行停掉了

很不穩定、被強行停掉了

很不穩定、被強行停掉了

在單節點的測試中,可以發現64個連接的時候,服務器傳輸速度還很穩定,但是到了128連接就發現發送32KB大小的消息,傳輸速度浮動都很大,所以預測rabbitmq單節點的性能極限應該在128連接發送16KB大小的消息。後經過測試單節點極限在128連接發送8KB大小的消息。

在集羣測試中,發現在32個連接發送1W個32KB大小的消息的時候,直接被強行停掉了,之後又測試了16KB,8KB,4KB的情況,發現只有4KB的情況下,才能穩定運行。由此大致得出集羣(鏡像隊列)的極限性能是32個連接每個連接發1W個4KB大小的消息。速度5000/s左右,CPU佔用350%-377%

與cinder聯調

1.    同時啓動rabbit1和rabbit2,cinder工作正常。

2.    rabbit1stop,cinder工作正常。

3.    把rabbit1恢復,rabbit2stop,cinder工作正常。

與ceilometer聯調

1.    同時啓動rabbit1和rabbit2,ceilometor工作正常。

2.    rabbit1stop,ceilometer工作正常。

3.    把rabbit1恢復,rabbit4stop,ceilometer工作正常。

與nova聯調

4.      同時啓動rabbit1和rabbit2,nova工作正常。

5.      rabbit1stop,nova工作正常。

6.      把rabbit1恢復,rabbit4stop,nova工作正常。

監控rabbitMQ的方案

一些基本情況

每個模塊的負責人會單獨監控自己的模塊,rabbitMQ的監控更傾向於發生問題之後的解決,比如purge掉隊列中的冗餘消息。另外,openstack中與rabbitmq相關的各個模塊用的是同一個rabbitmq的user,這也就是說,不需要單獨對某個模塊add user,並且每個模塊使用rabbitmq所建立的queue和exchange等都是自動完成的,也不需要care創建隊列的權限等。基於以上一些情況,個人制定了下面的監控方案。

命令行查看最基本的運行狀態

輸入sudo rabbitmqctl -n rabbit@rabbit1 status查看該節點目前的狀態

如果提示沒有連接到該節點,則表示該節點掛掉了,需要重新啓動。

如果能查看到該節點的狀態,則輸入sudo rabbitmqctl –n rabbit@rabbit1 list_connections查看連接是否都是running狀態, 如果有block狀態則表示該進程目前阻塞了。

在目前節點狀態查看中,可以查看已經內存使用率、磁盤剩餘空間等狀態。



所要監控的信息

內存佔用:超過60%報警。

磁盤佔用:超過70%報警。

sudo rabbitmqctl status



每個隊列的name、messages、memory。

隊列的消息數上限爲10*10^4個,memory最大爲512MB。如果超過這些閾值,就需要立即進行處理,以免影響整個服務正常運轉。

sudo rabbitmqctl list_queues name messages memory



每個連接的state、timeout。

在我們的整個服務中,每個連接的state都應該是running,最大延遲爲1s。如果狀態不是running或者延遲過高,則需要立即處理。

sudo rabbitmqctl list_connections host state timeout



如果相關閾值需要修改,與每個模塊相關負責人商議之後可修改閾值。



在192.168.8.14和192.168.8.35上,有兩個腳本,可以查看rabbitmq消息隊列狀態。

sudo sh /usr/local/bin/monitor_rabbitmq_queue_state.sh

根據提示來進行一些輸入就可以了。

截圖如下:

Web插件

查看connection exchange queue等狀態,消息數量,內存佔用,disc佔用等。需要根據實際情況判斷是否正常。

消息狀態:

節點狀態:



connection:

channel:

exchange:

queue:

policy:

一般來說rabbitMQ自帶各種流量閾值限制,如果掛掉一般都是因爲超過了閾值,要等實際運行的時候進行閾值調整。


轉自 http://blog.csdn.net/cugb1004101218/article/details/21243927?utm_source=tuicool&utm_medium=referral

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章