標籤:

RabbitMQ學習心得——RabbitMQ簡介(下)

這篇文章描述一下RabbitMQ中用到的名詞及其概念。

一、隊列

在AMQP模型中的隊列和其他的消息和任務隊列系統非常相似:他們存儲用於被應用程序消費的消息。並且和交換機共享一些屬性,但是也有自己額外的屬性。

  1. 名字(Name)
  2. 持久性(Durable):當broker重啟的時候,隊列依然存活。
  3. 互斥性(Exclusive):只被一個連接(connection)使用,而且當連接關閉後隊列即被刪除。
  4. 自動刪除(Auto-delete):當最後一個消費者退訂後即被刪除。
  5. 參數(Arguments):一些消息代理用他來完成類似與TTL的某些額外功能。

隊列在聲明(declare)後才能被使用。如果一個隊列尚不存在,聲明一個隊列會創建它。如果聲明的隊列已經存在,並且屬性完全相同,那麼此次聲明不會對原有隊列產生任何影響。如果聲明中的屬性與已存在隊列的屬性有差異,那麼一個錯誤代碼為406的通道級異常就會被拋出。

  • 對列名稱

應用可以取一個隊列的名字,也可以要broker生成一個隊列的名字。隊列的名字可以是255個字元的UTF-8。傳空字元串給隊列的名字參數,broker將產生一個唯一的名字給你的隊列。在同一個channel上使用一個空字元串作為隊列名參數調用子類的方法可能得到相同的隊列名。這是由於channel記住了最新產生的隊列名。

以「amq.」開始的隊列名,是留給broker內部使用的保留隊列名。以amq.定義一個隊列名將獲得一個channel級別的異常,異常碼為403(ACCESS_REFUSED)

  • 隊列持久化

持久化隊列(Durable queues)會被存儲在磁碟上,當消息代理(broker)重啟的時候,它依舊存在。沒有被持久化的隊列稱作暫存隊列(Transient queues)。並不是所有的場景和案例都需要將隊列持久化。

持久化的隊列並不會使得路由到它的消息也具有持久性。倘若消息代理掛掉了,重新啟動,那麼在重啟的過程中持久化隊列會被重新聲明,無論怎樣,只有經過持久化的消息才能被重新恢復。

二、綁定

綁定,顧名思義,是交換機將消息路由給隊列所遵循的規則。如果要指示交換機「E」將消息路由給隊列「Q」,那麼「Q」就需要與「E」進行綁定。綁定操作需要定義一個可選的路由鍵(routing key)屬性給某些類型的交換機。路由鍵的意義在於從發送給交換機的眾多消息中選擇出某些消息,將其路由給綁定的隊列。

使用這種分層的架構,使不可能的路由場景或者用直接發送到隊列非常難實現場景成為可能,並且避免了應用開發人員不得不做的某些重複工作。

如果AMQP的信息不能投遞到任何隊列(比如,由於沒有bindings到exchange上),她可以刪除信息也可以返回給發送者,完全取決於發送者消息屬性的設置。

三、消費者

與生產者相對應。生產者生產食物(消息),就贏由消費者去消費。不然消息沒有一點價值可言。應用消費消息有兩種方式:

  1. 將消息投遞給應用(「push API」),這是方式是被動的。
  2. 應用根據需要主動獲取消息 ("pull API"),這種方式是主動的。

使用push API,應用(application)需要明確表示出它在某個特定隊列里所感興趣的,想要消費的消息。如是,我們可以說應用註冊了一個消費者,或者說訂閱了一個隊列。一個隊列可以註冊多個消費者,也可以註冊一個獨享的消費者(當獨享消費者存在時,其他消費者即被排除在外)。

每個消費者(訂閱者)都有一個叫做消費者標籤的標識符。它可以被用來退訂消息。消費者標籤實際上是一個字元串。

四、消息確認

消費和處理消息的應用很有可能處理失敗或者發生某些衝突。也可能是網路的問題。這些問題導致AMQP的broker什麼時候該從隊列中移走消息?AMQP規範規定broker有兩個選擇可以做這個事:

  1. 在broker發送信息給應用之後(可以使用basic.deliver或者basic.get-ok兩個AMQP方法)
  2. 應用返回一個確認信息(使用basic.ack的AMQP方法)

第一種方式叫做自動確認模式,後面一種叫做手動確認模式。在手動確認模式中,應用程序選擇何時發送確認信息。可以是在收到消息之後,也可以是保存信息到資料庫之後,也可以是所有步驟都執行之後。

如果消費者死去而沒有發送任何的確認信息,broker將重新發送消息給另一個消費者,或者如果沒有一個消費是可用的,broker將一直等待(rabbitmq中沒有超時的概念),直到至少有一個消費者註冊到相同的隊列,他將把消息發送給這個註冊者。

  • 拒絕消息

消費者處理接收的消息,執行過程中可能會失敗。消費者可以通過駁回信息的方式告訴broker自己的執行過程失敗了。當駁回一個信息時,消費者可以要broker丟棄或者重新放回到隊列。當只有一個消費者註冊在隊列上時,注意不要不合理的駁回產生駁回,再入列,在消費的死循環!

  • 否定確認消息

消息可以使用basic.reject的AMQP方法駁回。但是有限制:沒有辦法駁回已經確認的信息。但是,如果你使用RabbitMQ,將有解決方案,RabbitMQ提供了一個AMQP 0-9-1的去擴展叫否定確認或者叫做否定回答。

  • 預抓信息

在多個消費者共享一個隊列的案例中,明確指定在收到下一個確認回執前每個消費者一次可以接受多少條消息是非常有用的。這可以在試圖批量發布消息的時候起到簡單的負載均衡和提高消息吞吐量的作用。

注意:RabbitMQ只提供channel級別的prefetch-count,不提供connection或者基本個數的預抓


推薦閱讀:

beanstalk和rabbitmq區別?

TAG:RabbitMQ |