消息中間件(RabbitMQ)04

一、rabbitmq實現了AMQP協議

      AMQP是應用層協議的一個開放標準,爲面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不同產品,不同的開發語言等條件的限制。目標是實現一種在全行業廣泛使用的標準消息中間件技術,以便降低企業和系統集成的開銷,並且向大衆提供工業級的集成服務。主要實現有 RabbitMQ。

二、AMQP包含的要素

    生產者:消息的創建者,發送到rabbitmq;

    消費者:連接到rabbitmq,訂閱到隊列上,消費消息,持續訂閱(basicConsumer)和單條訂閱(basicGet).

    消息:包含有效載荷和標籤,有效載荷指要傳輸的數據,,標籤描述了有效載荷,並且rabbitmq用它來決定誰獲得消息,消費者只能拿到有效載荷,並不知道生產者是誰。

    信道,概念:信道是生產消費者與rabbit通信的渠道,生產者publish或是消費者subscribe一個隊列都是通過信道來通信的。信道是建立在TCP連接上的虛擬連接,什麼意思呢?就是說rabbitmq在一條TCP上建立成百上千個信道來達到多個線程處理,這個TCP被多個線程共享,每個線程對應一個信道,信道在rabbit都有唯一的ID ,保證了信道私有性,對應上唯一的線程使用

(爲什麼不建立多個TCP連接呢?原因是rabbit保證性能,系統爲每個線程開闢一個TCP是非常消耗性能,每秒成百上千的建立銷燬TCP會嚴重消耗系統。所以rabbitmq選擇建立多個信道(建立在tcp的虛擬連接)連接到rabbit上。)

    交換器、隊列、綁定、路由鍵 :

     隊列通過路由鍵(routing  key,某種確定的規則)綁定到交換器,生產者將消息發佈到交換器,交換器根據綁定的路由鍵將消息路由到特定隊列,然後由訂閱這個隊列的消費者進行接收。

(詳細的解釋請查看:http://rabbitmq.mr-ping.com/AMQP/AMQP_0-9-1_Model_Explained.html

三、消息確認

        消費者收到的每一條消息都必須進行確認(自動確認和非自行確認,非自行確認下,rabbitmq會一直等待確認,除非忘了斷開)。

        消費者在聲明隊列時,可以指定autoAck參數,當autoAck=false時,RabbitMQ會等待消費者顯式發回ack信號後才從內存(和磁盤,如果是持久化消息的話)中移去消息。否則,RabbitMQ會在隊列中消息被消費後立即刪除它。

        採用消息確認機制後,只要令autoAck=false,消費者就有足夠的時間處理消息(任務),不用擔心處理消息過程中消費者進程掛掉後消息丟失的問題,因爲RabbitMQ會一直持有消息直到消費者顯式調用basicAck爲止。

        當autoAck=false時,對於RabbitMQ服務器端而言,隊列中的消息分成了兩部分:一部分是等待投遞給消費者的消息;一部分是已經投遞給消費者,但是還沒有收到消費者ack信號的消息。如果服務器端一直沒有收到消費者的ack信號,並且消費此消息的消費者已經斷開連接,則服務器端會安排該消息重新進入隊列,等待投遞給下一個消費者(也可能還是原來的那個消費者)。

        RabbitMQ不會爲未ack的消息設置超時時間,它判斷此消息是否需要重新投遞給消費者的唯一依據是消費該消息的消費者連接是否已經斷開。這麼設計的原因是RabbitMQ允許消費者消費一條消息的時間可以很久很久。

四、交換器的類型:

    共有四種direct,fanout,topic,headers,其種headers(幾乎和direct一樣)不實用,可以忽略。

    

直連型交換器(direct exchange)是根據消息攜帶的路由鍵(routing key)將消息投遞給對應隊列的。直連交換器用來處理消息的單播路由(unicast routing)(儘管它也可以處理多播路由)。下邊介紹它是如何工作的:

  • 將一個隊列綁定到某個交換機上,同時賦予該綁定一個路由鍵(routing key)
  • 當一個攜帶着路由鍵爲R的消息被髮送給直連交換器時,交換器會把它路由給綁定值同樣爲R的隊列。

直連交換器經常用來循環分發任務給多個工作者(workers)。當這樣做的時候,我們需要明白一點,在AMQP中,消息的負載均衡是發生在消費者(consumer)之間的,而不是隊列(queue)之間。

直連型交換器圖例:

 

扇型交換器(funout exchange)將消息路由給綁定到它身上的所有隊列,而不理會綁定的路由鍵。如果N個隊列綁定到某個扇型交換器上,當有消息發送給此扇型交換器時,交換器會將消息的拷貝分別發送給這所有的N個隊列。扇型用來交換器處理消息的廣播路由(broadcast routing)。

因爲扇型交換器投遞消息的拷貝到所有綁定到它的隊列,所以他的應用案例都極其相似:

  • 大規模多用戶在線(MMO)遊戲可以使用它來處理排行榜更新等全局事件
  • 體育新聞網站可以用它來近乎實時地將比分更新分發給移動客戶端
  • 分發系統使用它來廣播各種狀態和配置更新
  • 在羣聊的時候,它被用來分發消息給參與羣聊的用戶。

 扇型交換機圖例:

主題交換器(topic exchanges)通過對消息的路由鍵和隊列到交換機的綁定模式之間的匹配,將消息路由給一個或多個隊列 ,

通過使用“*”和“#”,使來自不同源頭的消息到達同一個隊列,”.”將路由鍵分爲了幾個標識符,“*”匹配1個,“#”匹配一個或多個。例如日誌處理:

假設有交換器log-exchange,

日誌級別有error,info,warning,

應用模塊有user,order,email,

服務器有 A、B、C、D

路由鍵的規則爲 服務器+“.”+日誌級別+“.”+應用模塊名,如:A. info .email。

1、要關注A服務器發送的所有應用錯誤的消息,怎麼做?

聲明隊列名稱爲“a-app-error-queue”並綁定到交換器上:channel. queueBind (‘a-app-error-queue’,’logs-change’,’A.error.*’)

2、關注B服務器發送的的所有日誌,怎麼辦?

聲明隊列名稱爲“b-all-queue”並綁定到交換器上:channel. queueBind (b-all-queue’,’logs-change’,’ B.#’)或channel. queueBind (b-all-queue’,’logs-change’,’ B.*.*’)

3、關注所有服務器發送的email的所有日誌,怎麼辦?

聲明隊列名稱爲“email-all-queue”並綁定到交換器上:channel. queueBind (email -all-queue’,’logs-change’,’ *.*.emal’)

4、想要接收所有日誌:channel->queue_bind(‘all-log’,’logs-change’,’#’)

 頭交換器(headers exchange)有時消息的路由操作會涉及到多個屬性,此時使用消息頭就比用路由鍵更容易表達,頭交換器(headers exchange)就是爲此而生的。頭交換器使用多個消息屬性來代替路由鍵建立路由規則。通過判斷消息頭的值能否與指定的綁定相匹配來確立路由規則。

我們可以綁定一個隊列到頭交換器上,並給他們之間的綁定使用多個用於匹配的頭(header)。這個案例中,消息代理得從應用開發者那兒取到更多一段信息,換句話說,它需要考慮某條消息(message)是需要部分匹配還是全部匹配。上邊說的“更多一段消息”就是"x-match"參數。當"x-match"設置爲“any”時,消息頭的任意一個值被匹配就可以滿足條件,而當"x-match"設置爲“all”的時候,就需要消息頭的所有值都匹配成功。

頭交換器可以視爲直連交換器的另一種表現形式。頭交換機能夠像直連交換機一樣工作,不同之處在於頭交換機的路由規則是建立在頭屬性值之上,而不是路由鍵。路由鍵必須是一個字符串,而頭屬性值則沒有這個約束,它們甚至可以是整數或者哈希值(字典)等。

五、虛擬主機

虛擬消息服務器,vhost,本質上就是一個mini版的mq服務器,有自己的隊列、交換器和綁定,最重要的,自己的權限機制。Vhost提供了邏輯上的分離,可以將衆多客戶端進行區分,又可以避免隊列和交換器的命名衝突。Vhost必須在連接時指定,rabbitmq包含缺省vhost:“/”,通過缺省用戶和口令guest進行訪問。

rabbitmq裏創建用戶,必須要被指派給至少一個vhost,並且只能訪問被指派內的隊列、交換器和綁定。Vhost必須通過rabbitmq的管理控制工具創建。

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