RabbitMQ的基礎概念和設計模式

一、RabbitMQ的基礎概念

  1. Broker
    Broker:簡單來說就是消息隊列服務器實體。中文意思:中間件。接受客戶端連接,實現AMQP消息隊列和路由功能的進程。一個broker裏可以開設多個vhost,用作不同用戶的權限分離。

RabbitMQ官網解釋

A RabbitMQ broker is a logical grouping of one or several Erlang
nodes, each running the RabbitMQ application and sharing users,
virtual hosts, queues, exchanges, bindings, and runtime parameters.
Sometimes we refer to the collection of nodes as a cluster.

  1. Virtual Host
    (1)國內博客解釋

每一個RabbitMQ服務器都能創建虛擬消息服務器,我們稱之爲虛擬主機。每一個vhost本質上是一個mini版的RabbitMQ服務器,擁有自己的交換機、隊列、綁定等,擁有自己的權限機制。vhost之於Rabbit就像虛擬機之於物理機一樣。他們通過在各個實例間提供邏輯上分離,允許爲不同的應用程序安全保密的運行數據,這很有用,它既能將同一個Rabbit的衆多客戶區分開來,又可以避免隊列和交換器的命名衝突。RabbitMQ提供了開箱即用的默認的虛擬主機“/”,如果不需要多個vhost可以直接使用這個默認的vhost,通過使用缺省的guest用戶名和guest密碼來訪問默認的vhost。
vhost之間是相互獨立的,這避免了各種命名的衝突,就像App中的沙盒的概念一樣,每個沙盒是相互獨立的,且只能訪問自己的沙盒,以保證非法訪問別的沙盒帶來的安全隱患。

vhost其實是一個虛擬概念,類似於權限控制組,一個Virtual
Host裏面可以有若干個Exchange和Queue,但是權限控制的最小粒度是Virtual Host。

(2)RabbitMQ官網解釋
https://www.rabbitmq.com/vhosts.html

Introduction RabbitMQ is multi-tenant system: connections, exchanges,
queues, bindings, user permissions, policies and some other things
belong to virtual hosts, logical groups of entities. If you are
familiar with virtual hosts in Apache or server blocks in Nginx, the
idea is similar. There is, however, one important difference: virtual
hosts in Apache are defined in the configuration file; that’s not the
case with RabbitMQ: virtual hosts are created and deleted using
rabbitmqctl or HTTP API instead.

Logical and Physical Separation Virtual hosts provide logical grouping
and separation of resources. Separation of physical resources is not a
goal of virtual hosts and should be considered an implementation
detail. For example, resource permissions in RabbitMQ are scoped per
virtual host. A user doesn’t have global permissions, only permissions
in one or more virtual hosts. User tags can be considered global
permissions but they are an exception to the rule. Therefore when
talking about user permissions it is very Important to clarify what
virtual host(s) they apply to.

Virtual Hosts and Client Connections A virtual host has a name. When
an AMQP 0-9-1 client connects to RabbitMQ, it specifies a vhost name
to connect to. If authentication succeeds and the username provided
was granted permissions to the vhost, connection is established.

Connections to a vhost can only operate on exchanges, queues,
bindings, and so on in that vhost. “Interconnection” of e.g. a queue
and an exchange in different vhosts is only possible when an
application connects to two vhosts at the same time. For example, an
application can consume from one vhost then republishes into the
other. This scenario can involve vhosts in different clusters or the
same cluster (or a single node). RabbitMQ Shovel plugin is one example
of such application.

(3)Apache對Vitual Host的定義

術語虛擬主機指的是在單一機器上運行多個網站 (例如 company1.example.com 和 company2.example.com)
。 虛擬主機可以“基於 IP”,即每個 IP 一個站點; 或者“基於名稱”, 即每個 IP
多個站點。這些站點運行在同一物理服務器上的事實不會明顯的透漏給最終用戶。 Apache 是第一個支持基於 IP 的虛擬主機的服務器。
Apache 版本 1.1 和更新的版本同時支持基於 IP 和基於名稱的虛擬主機。 基於名稱的虛擬主機有時候稱爲基於主機或非 IP
的虛擬主機.

(4)RabbitMQ的基礎 — 多租戶技術

多租戶技術(英語:multi-tenancy technology)或稱多重租賃技術,是一種軟件架構技術,它是在探討與實現如何於多用戶的環境下共用相同的系統或程序組件,並且仍可確保各用戶間數據的隔離性。 多租戶簡單來說是指一個單獨的實例可以爲多個組織服務。多租戶技術爲共用的數據中心內如何以單一系統架構與服務提供多數客戶端相同甚至可定製化的服務,並且仍然可以保障客戶的數據隔離。一個支持多租戶技術的系統需要在設計上對它的數據和配置進行虛擬分區,從而使系統的每個租戶或稱組織都能夠使用一個單獨的系統實例,並且每個租戶都可以根據自己的需求對租用的系統實例進行個性化配置。 多租戶技術可以實現多個租戶之間共享系統實例,同時又可以實現租戶的系統實例的個性化定製。通過使用多租戶技術可以保證系統共性的部分被共享,個性的部分被單獨隔離。通過在多個租戶之間的資源複用,運營管理維護資源,有效節省開發應用的成本。而且,在租戶之間共享應用程序的單個實例,可以實現當應用程序升級時,所有租戶可以同時升級。同時,因爲多個租戶共享一份系統的核心代碼,因此當系統升級時,只需要升級相同的核心代碼即可。

  1. Exchange
    接受生產者發送的消息,並根據Binding規則將消息路由給服務器中的隊列。ExchangeType決定了Exchange路由消息的行爲,例如,在RabbitMQ中,ExchangeType有direct、Fanout和Topic三種,不同類型的Exchange路由的行爲是不一樣的。

  2. Queue
    消息隊列,用於存儲還未被消費者消費的消息。

RabbitMQ官方對隊列命名的解釋

Queues have names so that applications can reference them.

Applications may pick queue names or ask the broker to generate a name
for them. Queue names may be up to 255 bytes of UTF-8 characters.

Queue names starting with “amq.” are reserved for internal use by the
broker. Attempts to declare a queue with a name that violates this
rule will result in a channel-level exception with reply code 403
(ACCESS_REFUSED).

  1. Message
    由Header和Body組成,Header是由生產者添加的各種屬性的集合,包括Message是否被持久化、由哪個Message Queue接受、優先級是多少等。而Body是真正需要傳輸的APP數據。

  2. Connection
    連接,對於RabbitMQ而言,其實就是一個位於客戶端和Broker之間的TCP連接。

  3. Channel
    信道,僅僅創建了客戶端到Broker之間的連接後,客戶端還是不能發送消息的。需要爲每一個Connection創建Channel,AMQP協議規定只有通過Channel才能執行AMQP的命令。一個Connection可以包含多個Channel。之所以需要Channel,是因爲TCP連接的建立和釋放都是十分昂貴的,如果一個客戶端每一個線程都需要與Broker交互,如果每一個線程都建立一個TCP連接,暫且不考慮TCP連接是否浪費,就算操作系統也無法承受每秒建立如此多的TCP連接。RabbitMQ建議客戶端線程之間不要共用Channel,至少要保證共用Channel的線程發送消息必須是串行的,但是建議儘量共用Connection。

  4. Command
    AMQP的命令,客戶端通過Command完成與AMQP服務器的交互來實現自身的邏輯。例如在RabbitMQ中,客戶端可以通過publish命令發送消息,txSelect開啓一個事務,txCommit提交一個事務。
    在這裏插入圖片描述

  5. AMQP協議棧
    摘錄RabbitMQ官網 對AMQP的解釋 https://www.rabbitmq.com/protocol.html :

The AMQP protocol is a binary protocol with modern features: it is
multi-channel, negotiated, asynchronous, secure, portable, neutral,
and efficient. AMQP is usefully split into two layers:

The functional layer defines a set of commands (grouped into logical
classes of functionality) that do useful work on behalf of the
application. The transport layer that carries these methods from
application to server, and back, and which handles channel
multiplexing, framing, content encoding, heart-beating, data
representation, and error handling. One could replace the transport
layer with arbitrary transports without changing the
application-visible functionality of the protocol. One could also use
the same transport layer for different high-level protocols.

二、RabbitMQ的設計模式

RabbitMQ 使用的是發佈訂閱模式

觀察者模式
所謂觀察者模式,其實就是爲了實現松耦合(loosely coupled)。
用《Head First設計模式》裏的氣象站爲例子,每當氣象測量數據有更新,changed()方法就會被調用,於是我們可以在changed()方法裏面,更新氣象儀器上的數據,比如溫度、氣壓等等。
但是這樣寫有個問題,就是如果以後我們想在changed()方法被調用時,更新更多的信息,比如說溼度,那就要去修改changed()方法的代碼,這就是緊耦合的壞處。
怎麼解決呢?使用觀察者模式,面向接口編程,實現松耦合。
觀察者模式裏面,changed()方法所在的實例對象,就是被觀察者(Subject,或者叫Observable),它只需維護一套觀察者(Observer)的集合,這些Observer實現相同的接口,Subject只需要知道,通知Observer時,需要調用哪個統一方法就好了:
在這裏插入圖片描述

發佈訂閱模式
大概很多人都和我一樣,覺得發佈訂閱模式裏的Publisher,就是觀察者模式裏的Subject,而Subscriber,就是Observer。Publisher變化時,就主動去通知Subscriber。
其實並不是。
在發佈訂閱模式裏,發佈者,並不會直接通知訂閱者,換句話說,發佈者和訂閱者,彼此互不相識。
互不相識?那他們之間如何交流?
答案是,通過第三者,也就是在消息隊列裏面,我們常說的經紀人Broker
在這裏插入圖片描述
發佈者只需告訴Broker,我要發的消息,topic是AAA;
訂閱者只需告訴Broker,我要訂閱topic是AAA的消息;
於是,當Broker收到發佈者發過來消息,並且topic是AAA時,就會把消息推送給訂閱了topic是AAA的訂閱者。當然也有可能是訂閱者自己過來拉取,看具體實現。
也就是說,發佈訂閱模式裏,發佈者和訂閱者,不是松耦合,而是完全解耦的。

總結
從表面上看:

觀察者模式裏,只有兩個角色 —— 觀察者 + 被觀察者
而發佈訂閱模式裏,卻不僅僅只有發佈者和訂閱者兩個角色,還有一個經常被我們忽略的 —— 經紀人Broker
往更深層次講:

觀察者和被觀察者,是松耦合的關係
發佈者和訂閱者,則完全不存在耦合
從使用層面上講:

觀察者模式,多用於單個應用內部
發佈訂閱模式,則更多的是一種跨應用的模式(cross-application pattern),比如我們常用的消息中間件

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