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),比如我们常用的消息中间件

猜你喜欢

转载自blog.csdn.net/jike11231/article/details/107102130