很久以前聽過消息隊(duì)列,但一直沒有機(jī)會用到。這次的項(xiàng)目便用到了,為此揭開神秘的面紗。
簡單總結(jié)下:
rabbit有好幾種模式:
我用的 發(fā)布/訂閱模式
produce,exchange,queue,cusumer
在生產(chǎn)者客戶端,聲明exchange,binding,
消息發(fā)送到rabbitmq服務(wù)器,消費(fèi)者客戶端進(jìn)行訂閱,聲明exchange,binding,queue,
消息發(fā)送到exchange,exchange分發(fā)到綁定它的所有queue,
在消費(fèi)端,寫listener,根據(jù)業(yè)務(wù)編號區(qū)分對應(yīng)的queue接收的消息。
在此貼一篇文章。
1. 定義
消息隊(duì)列:在消息的傳輸過程中保存消息的的容器。
這是一個(gè)較為經(jīng)典的消費(fèi)-生產(chǎn)者模型,說起來比較抽象,打個(gè)比方:A線程需要給B線程發(fā)送消息(A、B線程不一定是在同一臺機(jī)器上的),A線程先把消息發(fā)送到消息隊(duì)列服務(wù)器上,然后B線程去讀取或是訂閱消息服務(wù)器上消息隊(duì)列中的消息,線程A和B之間并沒有進(jìn)行直接通信。MQ服務(wù)器在中間起到中繼的作用。
2. 適用的應(yīng)用場景
比較適合異步傳輸,這里解釋一下什么是異步和同步。
異步:發(fā)送方不關(guān)心消息有沒有發(fā)送成功,只發(fā)送消息,不去獲取消息是否發(fā)送成功。
同步:發(fā)送方關(guān)心消息是否發(fā)送成功,發(fā)送消息后,會等待接收方返回狀態(tài)碼,根據(jù)狀態(tài)碼來判斷是否發(fā)送成功,然后執(zhí)行相對于的動(dòng)作。
下邊以Http中的同步和異步為例:
如:普通的B/S架構(gòu)客戶端和服務(wù)器端之間的通信就是同步的,即提交請求 ---> 等待服務(wù)器處理完畢返回消息 ---> 拿到服務(wù)器返回的消息,處理完畢。
如:Ajax技術(shù)就是異步的,請求通過事件觸發(fā) ---> 服務(wù)器處理(瀏覽器不用等待,仍可以做其他的事情) ---> 處理完畢。
有人可能會好奇說應(yīng)用場景怎么說到了同步和異步,那說明你還不是很理解技術(shù)和應(yīng)用場景之間的緊密聯(lián)系。
3. RabbitMQ
在消息隊(duì)列中有很多類似的產(chǎn)品,以后我會獨(dú)立發(fā)一篇博文來經(jīng)行說明。我們這里以RabbitMQ為例。
RabbitMQ是AMQP(高級消息隊(duì)列協(xié)議)的一個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn),關(guān)于它的快速入門,可以在這里查看:http://www.rabbitmq.com/getstarted.html。
3.1. 角色概念
每個(gè)開源項(xiàng)目都有自己的設(shè)計(jì)方法以及模塊角色,RabbitMQ也不例外。結(jié)構(gòu)圖如下:
Broker:即消息隊(duì)列服務(wù)器實(shí)體
Exchange:消息交換機(jī),它指定消息按什么規(guī)則,路由到哪個(gè)隊(duì)列。
Queue:消息隊(duì)列載體,每個(gè)消息都會被投入到一個(gè)或多個(gè)隊(duì)列。
Binding:綁定,它的作用就是把exchange和queue按照路由規(guī)則綁定起來。
Routing Key:路由關(guān)鍵字,exchange根據(jù)這個(gè)關(guān)鍵字進(jìn)行消息投遞。
vhost:虛擬主機(jī),一個(gè)broker里可以開設(shè)多個(gè)vhost,用作不同用戶的權(quán)限分離。
producer:消息生產(chǎn)者,就是投遞消息的程序。
consumer:消息消費(fèi)者,就是接受消息的程序。
channel:消息通道,在客戶端的每個(gè)連接里,可建立多個(gè)channel,每個(gè)channel代表一個(gè)會話任務(wù)。
3.2. 工作過程
生產(chǎn)者客戶端:
客戶端連接到RabbitMQ服務(wù)器上,打開一個(gè)消息通道(channel);
客戶端聲明一個(gè)消息交換機(jī)(exchange),并設(shè)置相關(guān)屬性。
客戶端聲明一個(gè)消息隊(duì)列(queue),并設(shè)置相關(guān)屬性。
客戶端使用routing key在消息交換機(jī)(exchange)和消息隊(duì)列(queue)中建立好綁定關(guān)系。
客戶端投遞消息都消息交換機(jī)(exchange)上
客戶端關(guān)閉消息通道(channel)以及和服務(wù)器的連接。
服務(wù)器端:
exchange接收到消息后,根據(jù)消息的key(這個(gè)key的產(chǎn)生規(guī)則暫時(shí)沒研究,有知道的小伙伴可以留言告訴我)和以及設(shè)置的binding,進(jìn)行消息路由,將消息投遞到一個(gè)或多個(gè)消息隊(duì)列中。
關(guān)于exchange也有幾個(gè)類型:
(1). Direct交換機(jī):完全根據(jù)key進(jìn)行投遞。例如,綁定時(shí)設(shè)置了routing key為abc,客戶端提交信息提交信息時(shí)只有設(shè)置了key為abc的才會投遞到隊(duì)列;
(2).Topic交換機(jī):在key進(jìn)行模式匹配后進(jìn)行投遞。例如:符號”#”匹配一個(gè)或多個(gè)字符,符號”*”匹配一串連續(xù)的字母字符,例如”abc.#”可以匹配”abc.def.ghi”,而”abc.*”只可以匹配”abc.def”。
(3).Fanout交換機(jī):它采取廣播模式,消息進(jìn)來時(shí),將會被投遞到與改交換機(jī)綁定的所有隊(duì)列中。
消費(fèi)者客戶端:
(暫時(shí)未研究,后續(xù)更新)
3.3. RabbitMQ的消息持久化
RabbitMQ支持?jǐn)?shù)據(jù)持久化,也就是把數(shù)據(jù)寫在磁盤上,可以增加數(shù)據(jù)的安全性。消息隊(duì)列持久化包括三個(gè)部分:
消息交換機(jī)(exchange)持久化,在聲明時(shí)指定durable為1
消息隊(duì)列(queue)持久化,在聲明時(shí)指定durable為1
消息持久化,在投遞時(shí)指定delivery_mode為2(1是非持久化)
如果消息交換機(jī)(exchange)和消息隊(duì)列(queue)都是持久化的話,那么他們之間的綁定(Binding)也是持久化的。如果消息交換機(jī)和消息隊(duì)列之間一個(gè)持久化、一個(gè)非持久化,那么就不允許綁定。