天天看點

RabbitMQ的幾種典型使用場景

rabbitmq首頁:https://www.rabbitmq.com/

amqp

amqp協定是一個進階抽象層消息通信協定,rabbitmq是amqp協定的實作。它主要包括以下元件:

RabbitMQ的幾種典型使用場景

1.server(broker): 接受用戶端連接配接,實作amqp消息隊列和路由功能的程序。

2.virtual host:其實是一個虛拟概念,類似于權限控制組,一個virtual host裡面可以有若幹個exchange和queue,但是權限控制的最小粒度是virtual host

3.exchange:接受生産者發送的消息,并根據binding規則将消息路由給伺服器中的隊列。exchangetype決定了exchange路由消息的行為,例如,在rabbitmq中,exchangetype有direct、fanout和topic三種,不同類型的exchange路由的行為是不一樣的。

4.message queue:消息隊列,用于存儲還未被消費者消費的消息。

5.message: 由header和body組成,header是由生産者添加的各種屬性的集合,包括message是否被持久化、由哪個message queue接受、優先級是多少等。而body是真正需要傳輸的app資料。

6.binding:binding聯系了exchange與message queue。exchange在與多個message queue發生binding後會生成一張路由表,路由表中存儲着message queue所需消息的限制條件即binding key。當exchange收到message時會解析其header得到routing key,exchange根據routing key與exchange type将message路由到message queue。binding key由consumer在binding exchange與message queue時指定,而routing key由producer發送message時指定,兩者的比對方式由exchange type決定。 

7.connection:連接配接,對于rabbitmq而言,其實就是一個位于用戶端和broker之間的tcp連接配接。

8.channel:信道,僅僅建立了用戶端到broker之間的連接配接後,用戶端還是不能發送消息的。需要為每一個connection建立channel,amqp協定規定隻有通過channel才能執行amqp的指令。一個connection可以包含多個channel。之是以需要channel,是因為tcp連接配接的建立和釋放都是十分昂貴的,如果一個用戶端每一個線程都需要與broker互動,如果每一個線程都建立一個tcp連接配接,暫且不考慮tcp連接配接是否浪費,就算作業系統也無法承受每秒建立如此多的tcp連接配接。rabbitmq建議用戶端線程之間不要共用channel,至少要保證共用channel的線程發送消息必須是串行的,但是建議盡量共用connection。

9.command:amqp的指令,用戶端通過command完成與amqp伺服器的互動來實作自身的邏輯。例如在rabbitmq中,用戶端可以通過publish指令發送消息,txselect開啟一個事務,txcommit送出一個事務。

在了解了amqp模型以後,需要簡單介紹一下amqp的協定棧,amqp協定本身包括三層:

RabbitMQ的幾種典型使用場景

1.module layer,位于協定最高層,主要定義了一些供用戶端調用的指令,用戶端可以利用這些指令實作自己的業務邏輯,例如,用戶端可以通過queue.declare聲明一個隊列,利用consume指令擷取一個隊列中的消息。

2.session layer,主要負責将用戶端的指令發送給伺服器,在将伺服器端的應答傳回給用戶端,主要為用戶端與伺服器之間通信提供可靠性、同步機制和錯誤處理。

3.transport layer,主要傳輸二進制資料流,提供幀的處理、信道複用、錯誤檢測和資料表示。

rabbitmq使用場景

學習rabbitmq的使用場景,來自官方教程:https://www.rabbitmq.com/getstarted.html

場景1:單發送單接收

使用場景:簡單的發送與接收,沒有特别的處理。

RabbitMQ的幾種典型使用場景

producer:

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

consumer:

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

場景2:單發送多接收

使用場景:一個發送端,多個接收端,如分布式的任務派發。為了保證消息發送的可靠性,不丢失消息,使消息持久化了。同時為了防止接收端在處理消息時down掉,隻有在消息處理完成後才發送ack消息。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

發送端和場景1不同點:

1、使用“task_queue”聲明了另一個queue,因為rabbitmq不容許聲明2個相同名稱、配置不同的queue

2、使"task_queue"的queue的durable的屬性為true,即使消息隊列durable

3、使用messageproperties.persistent_text_plain使消息durable

when rabbitmq quits or crashes it will forget the queues and messages unless you tell it not to. two things are required to make sure that messages aren't lost: we need to mark both the queue and messages as durable.

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

接收端和場景1不同點:

1、使用“task_queue”聲明消息隊列,并使消息隊列durable

2、在使用channel.basicconsume接收消息時使autoack為false,即不自動會發ack,由channel.basicack()在消息處理完成後發送消息。

3、使用了channel.basicqos(1)保證在接收端一個消息沒有處理完時不會接收另一個消息,即接收端發送了ack後才會接收下一個消息。在這種情況下發送端會嘗試把消息發送給下一個not busy的接收端。

注意點:

1)it's a common mistake to miss the basicack. it's an easy error, but the consequences are serious. messages will be redelivered when your client quits (which may look like random redelivery), but rabbitmq will eat more and more memory as it won't be able to release any unacked messages.

2)note on message persistence

marking messages as persistent doesn't fully guarantee that a message won't be lost. although it tells rabbitmq to save the message to disk, there is still a short time window when rabbitmq has accepted a message and hasn't saved it yet. also, rabbitmq doesn't do fsync(2) for every message -- it may be just saved to cache and not really written to the disk. the persistence guarantees aren't strong, but it's more than enough for our simple task queue. if you need a stronger guarantee you can wrap the publishing code in atransaction.

3)note about queue size

if all the workers are busy, your queue can fill up. you will want to keep an eye on that, and maybe add more workers, or have some other strategy.

場景3:publish/subscribe

使用場景:釋出、訂閱模式,發送端發送廣播消息,多個接收端接收。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

發送端:

發送消息到一個名為“logs”的exchange上,使用“fanout”方式發送,即廣播消息,不需要使用queue,發送端不需要關心誰接收。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

接收端:

1、聲明名為“logs”的exchange的,方式為"fanout",和發送端一樣。

2、channel.queuedeclare().getqueue();該語句得到一個随機名稱的queue,該queue的類型為non-durable、exclusive、auto-delete的,将該queue綁定到上面的exchange上接收消息。

3、注意binding queue的時候,channel.queuebind()的第三個參數routing key為空,即所有的消息都接收。如果這個值不為空,在exchange type為“fanout”方式下該值被忽略!

場景4:routing (按路線發送接收)

使用場景:發送端按routing key發送消息,不同的接收端按不同的routing key接收消息。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

發送端和場景3的差別:

1、exchange的type為direct

2、發送消息的時候加入了routing key

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

接收端和場景3的差別:

在綁定queue和exchange的時候使用了routing key,即從該exchange上隻接收routing key指定的消息。

場景5:topics (按topic發送接收)

使用場景:發送端不隻按固定的routing key發送消息,而是按字元串“比對”發送,接收端同樣如此。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

發送端和場景4的差別:

1、exchange的type為topic

2、發送消息的routing key不是固定的單詞,而是比對字元串,如"*.lu.#",*比對一個單詞,#比對0個或多個單詞。

RabbitMQ的幾種典型使用場景
RabbitMQ的幾種典型使用場景

接收端和場景4的差別:

2、接收消息的routing key不是固定的單詞,而是比對字元串。

topic exchange

topic exchange is powerful and can behave like other exchanges. when a queue is bound with "#" (hash) binding key - it will receive all the messages, regardless of the routing key - like in fanout exchange. when special characters "*" (star) and "#" (hash) aren't used in bindings, the topic exchange will behave just like a direct one.

參考:

https://www.rabbitmq.com/getstarted.html

http://backend.blog.163.com/blog/static/202294126201322215551999/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

http://www.cnblogs.com/luxiaoxun/p/3918054.html