消息服務 - RabbitMQ 基礎入門

rabbitmq

RabbitMQ官方入門教程

本文算是實現對入門教程的 java版本翻譯吧。本文中演示代碼地址

1. 安裝

  1. 先安裝 erlang (安裝網上提供的教程安裝erlang)

  2. 在安裝 rabbitmq-server
    下載rabbitmq的安裝包的時候選擇 tar.xz 直接解壓就可以了

  3. 啟動/停止

#啟動rabbitmq
#進入安裝目錄的sbin 目錄,執行
./rabbitmq-server -detached

#關閉rabbitmq
./rabbitmqctl stop


2.用戶權限

guest/guest 現在只能在localhost使用,不能遠程使用

需要添加用戶和權限

參考文章 RabbitMQ用戶角色及權限控制

例如:

####添加用戶:

$sudo rabbitmqctl add_user  user_admin  passwd_admin  

#####修改角色為 administrator:

$sudo rabbitmqctl set_user_tags user_admin administrator

上面的操作有了,可能還是為在日志中提示 user_admin在 vhost '/' 權限不夠

則執行下面的操作:

######修改權限
$sudo rabbitmqctl  set_permissions -p /  user_admin '.*' '.*' '.*'

3.rabbitmq 的使用

3.1 工作隊列(workqueues) 模式

注意的點:

  1. 工作隊列中的消息被所有的消費者共享。
  2. rabbitmq在路由消息到消費者的時候使用輪詢(round-robin)的方式,找到第n個消費者來消費消息
  3. ack(ackownledgment)機制確保消息被消費,不出現消息沒有消費就從內存中刪除的情況

3.1.1 ack機制(Message acknowledgment)

RabbitMQ 支持消息確認,當消費者(Consumer)接受到消息并且處理完成之后,回給RabbitMQ 發送一個確認消息,Rabbitmq這個時候可以隨意的刪除這個消息

如果消費者die ,但是沒有發送確認消息,這個時候RabbitMQ會認為消息沒有完全處理,這個時候會這個消息重新放到隊列之中,使用輪詢的方式分配給其他的消費者消費

RabbitMQ 默認開啟了確認機制,使用的時候設置 autoAck = true 來關閉確認機制,設置autoAck = false 則開啟

3.1.2 消息持久化(Message durability)

啟動消息持久化,需要在申明channel的時候設置持久化屬性為true

boolean durable = true;
channel.queueDeclare("hello", durable, false, false, null);

一個確定了是否持久化的隊列,不能再修改durable的值

設置隊列為持久化隊列之后,需要設置下消息的屬性,例如設置屬性為MessageProperties (實現了 BasicProperties)

channel.basicPublish("", "task_queue",
            MessageProperties.PERSISTENT_TEXT_PLAIN,
            message.getBytes());

使用持久化消息并不能完全保證消息的持久化,應為消息可能先保存在緩存,后面保存到硬盤上,不過對于一般的task是完全足夠的,如果想要確保完全的持久化,可以結合 publisher confirms 來實現

3.1.3 公平分配(Fair dispatch)

通過設置prefetchCount 的值,控制一個消費者接受的任務數量

int prefetchCount = 1;
channel.basicQos(prefetchCount);

如上面的設置,當一個消費者還有沒有處理完的任務的時候,rabbitmq不會分配任務給他

開啟管理功能

rabbitmq-plugins enable rabbitmq_management

web管理界面: http://server-name:15672/


3.2 發布訂閱(Publish/Subscribe)模式

使用發布訂閱模式,一條消息會被發送給多個消費者消費

使用示例說明:

創建一個日志的生產者 EmitLog 來發布日志,使用多個日志接受者ReceiveLogs
創建兩個接受者,一個把日志往硬盤上面寫,一個把日志打印到顯示器。整個過程發布日志
的只有一個。日志被廣播到多個接受者

1.1 交換(Exchanges)

在rabbitmq的消息模型中

生產者-->發送消息的一端

隊列--> 消息緩沖區

消費者-->消費消息的一端

rabbitmq的核心思想中,生產者通常不直接發送消息給一個隊列,事實上,
生產者也不知道把消息發送給哪個隊列

實際上,生成這是把消息發送給一個Exchange,這個Exchange一方面從生產者那邊接受消息,
一方面推送消息給隊列(queue),exchange清楚的知道自己接受的消息要怎么處理——是追加到
一個指定的隊列?還是追加到多個隊列?還是直接丟棄?具體做法要根據exchange的類型(type)
來定

可以通過下面的指令列出exchange的類型

./rabbitmqctl list_exchanges

exchange的類型:

  1. direct
  2. topic
  3. headers
  4. fanout

之前的例子中沒有使用exchange是因為我們使用了默認的exchange 即使用空字符串"" 來定義的
(默認exchange的消息會被發送到指明的routingKey的隊列中)

channel.basicPublish("", "hello", null, message.getBytes());

現在創建一個exchange并發布

channel.exchangeDeclare("logs", "fanout");
channel.basicPublish( "logs", "", null, message.getBytes());

1.2 臨時隊列(Temporary queues)

使用無參的 queueDeclare() 方法可以創建一個非持久化的、獨立的、自動刪除的、名稱隨機的一個
隊列。例如:產生一個名為 amq.gen-JzTY20BRgKO-HjmUJj0wLg 的隊列

String queueName = channel.queueDeclare().getQueue();

1.3 綁定(Bindings)

之前說過,消息分配到哪個隊列是有exchange來處理的,那么要確定消息去哪兒,就需要明確隊列和exchange
的關系。這個過程稱為binding

channel.queueBind(queueName, "logs", "");

3.3 路由(Routing)

之前的發布訂閱示例中,我們使用的是廣播消息,所有的接受者都能接受。使用routing之后
能夠讓接收者只接收消息的一個子集。例如之前的示例中,只有錯誤級別的日志寫到硬盤,所有的
的錯誤全部打印

1.bindings

在綁定的過程中加上 routingKey,為了同 basic_publish 區分,我們稱之為 binding key

channel.queueBind(queueName, EXCHANGE_NAME, "black");

2. Direct exchange

fanout exchange :只適合無腦的廣播模式

direct exchange :消息會被分配到與消費的routing key 對應的 binding key的隊列上,匹配不上的
消息直接丟棄

image

如圖:direct 的 exchange X 關聯了兩個隊列 Q1、Q2,Q1的 binding key=orange
,Q2的綁定了兩個key black 和 green

在這種情況下:

routing key=orange的消息會被 exchange X 傳遞給 Q1

routing key=black 或者 routing key=green 的消息會被 exchange X 傳遞給 Q2

3. 多綁定 (Multiple bindings)

direct-exchange-multiple

如圖,對direct exchange 同時使用 binding key =black 綁定Q1、Q2,這個時候
direct的exchange就同之前的fanout的一樣了,直接廣播消息了

4. 測試

測試時候一個開兩個接收者,一個設置級別為 error ,一個設置為 info,error
然后開兩個生產者 分別發送 error 級別的消息和info級別的消息

觀察接收情況


3.4 主題(Topic)模式

在前面的日志例子中,我們可以通過級別來區分日志,但是我們還想通過日志來源來區分日志
就像unix tool 中的syslog,他能通過 級別(info/warn/error)和 來源(auth/cron/kern)來
路由日志

例如:我們只處理來自“cron” 的 “error”級別的日志,同時打印來自“kern”的所有級別的
日志

要實現這種要,我們就需要使用 topic exchange

1. Topic exchange

topic exchange 的 routing key必須是 一個或者英文單詞,中間使用點隔開的方式,
最大長度是255字節

binding key 必須是相同格式,topic exchange 的邏輯和direct 很相似,消息只會分配到匹配的binding key的隊列

  1. *(星) 代表一個單詞
  2. #(哈希)代表零個或者多個單詞

例如:

topic-example

在這個例子中,接收動物消息,消息會被發送到一個擁有三個單詞(兩個點隔開)的 routing key
格式為 <speed>.<color>.<species>

Q1綁定了 binding key“ *.orange.* ”, Q2 綁定了 “ *.*.rabbit” 和 “lazy.#”

Q1只對顏色為 orange的消息感興趣

Q2關心所有的rabbit 和 lazy的消息

routing key 為 quick.orange.rabbit既會被發送到Q1 也會被發送到 Q2
lazy.orange.elephant --> Q1,Q2
quick.orange.fox --> Q1
lazy.brown.fox --> Q2
lazy.pink.rabbit --> Q2(有兩個binding key 匹配的情況下依然只會被發送一次)
quick.brown.fox --> 匹配不上,直接丟棄
lazy.orange.male.rabbit -->Q2 (匹配上了"lazy.#")

當不使用 * 或者 # 站位符的時候,topic exchange表現的就和direct 是一樣的


3.5 RPC

這一節使用 RabbitMQ 建立一個RPC系統:一個客戶端和一個可擴展的服務器

本示例中在客戶端調用一個call 方法,服務端返回一個Fibonacci 數列的值

關于使用rpc的幾點建議:

  1. 本地方法和遠程方法要定義明確,一目了然

  2. 系統加注釋,是組件之間的依賴清晰可見

  3. 異常處理,當rpc 服務器出現異常的時候,客戶端改如何處理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,825評論 18 139
  • 來源 RabbitMQ是用Erlang實現的一個高并發高可靠AMQP消息隊列服務器。支持消息的持久化、事務、擁塞控...
    jiangmo閱讀 10,378評論 2 34
  • 1. 歷史 RabbitMQ是一個由erlang開發的AMQP(Advanced Message Queue )的...
    高廣超閱讀 6,111評論 3 51
  • 1 RabbitMQ安裝部署 這里是ErLang環境的下載地址http://www.erlang.org/down...
    Bobby0322閱讀 2,251評論 0 11
  • rabbitMQ是一款基于AMQP協議的消息中間件,它能夠在應用之間提供可靠的消息傳輸。在易用性,擴展性,高可用性...
    點融黑幫閱讀 3,021評論 3 41