全部开发者教程

RabbitMQ 入门教程

RabbitMQ 简介
RabbitMQ 简介

RabbitMQ 核心基础概念详解

1. 前言

Hello,大家好。本节会为同学们介绍 RabbitMQ 中的核心基础概念。这些核心基础概念组成 RabbitMQ 的基本元素,贯穿整个 RabbitMQ 的始终,如果我们不了解这些基础概念,那么当我们在使用 RabbitMQ 时,就会一脸懵,所以,在使用 RabbitMQ 之前,充分了解 RabbitMQ 的这些基础概念是非常有必要的。

本节主要内容:

  • AMQP 协议与 RabbitMQ 的联系;

  • RabbitMQ 基础概念梳理;

  • RabbitMQ 基础概念详解。

希望各位同学可以完全理解本节内容,这对学习 RabbitMQ 有着至关重要的作用。

2. AMQP 协议与 RabbitMQ 的联系

2.1 什么是 AMQP 协议

说起 AMQP 协议,我们可能会感到有点陌生,那么为什么还要了解 AMQP 协议呢? 因为了解什么是 AMQP 协议可以为我们学习 RabbitMQ 打下知识基础,让我们很清楚的知道 RabbitMQ 是用来做什么的。

AMQP 协议,即 Advanced Message Queuing Protocol,直译为高级消息队列协议,我们只要知道 AMQP 协议就是一个高级消息队列协议就行了。

2.2 与 RabbitMQ 的联系

AMQP 协议由三大模块组成,分别是交换机、消息队列、消息队列路由。通过这三大模块间的配合,可以实现对消息的发送、消息的监听等功能。

RabbitMQ 就是借鉴了 AMQP 协议的组成模块,在 AMQP 协议的基础上,对这些模块进行整合、拓展,并最终形成了基于 erlang 语言和 AMQP 协议的一个完备的消息中间件,因此,在 RabbitMQ 中,有些基础概念是和 AMQP 协议中的是几乎一样的,而有些概念确是 AMQP 协议中没有的。

而无论 AMQP 协议中有没有其他的概念,在这里会一并介绍。

3. RabbitMQ 基础概念梳理

在详细开始介绍 RabbitMQ 的基础概念之前,让我们先来看一下,在 RabbitMQ 中都有哪些基础概念需要我们知道。

序号 名称
01 消息
02 虚拟主机
03 交换机
04 路由 Key
05 频道
06 消息队列
07 生产者
08 消费者

Tips: 上述清单中的生产者与消费者概念,并不是 RabbitMQ 中特有的概念,考虑到学习本课程的同学基础,在这里就一并进行介绍了。

4. RabbitMQ 基础概念详解

4.1 生产者与消费者

定义:

在了解什么是生产者与消费者时,我们可以先不从计算机专业的角度考虑什么是生产者与消费者,我们可以先来了解它们的字面意思。从生活角度考虑,生产者就是生产某某东西的人,而消费者就是消费某某东西的人,它们两个一个是生产,一个是消费,且保持着一种先生产后消费的关系。

针对于计算机专业角度来说,生产者就是生产一条数据的手段或者途径,而消费者则是消费一条数据的手段或者途径。在 RabbitMQ 中,生产者指的就是具备生产一条消息能力的方法,消费者指的就是具备消费一条消息能力的方法。

代码实现:

那么我们如何在 RabbitMQ 中来定义一个生产者和一个消费者呢?接下来就让我们来看一下 RabbitMQ 中生产者与消费者的基础通用 API :

在 RabbitMQ 中要想声明一个生产者,我们首先需要与 RabbitMQ Server 建立通信,即将我们的应用程序与 RabbitMQ 的服务器建立链接,如下代码所示:

ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort("5672");
Connection connection = connectionFactory.newConnection();

代码解释:

第 1 行,我们实例化了一个 RabbitMQ 的链接工厂,这是与 RabbitMQ 服务器建立链接的必要基础操作。

第 2-3 行,我们使用我们实例化的链接工厂中的 setHost 和 setPort 方法来设置我们需要链接的 RabbitMQ 服务器的 ip 地址,以及端口号,RabbitMQ 服务默认的端口号为 5672。

第 4 行,在将 RabbitMQ 服务的 host 和 port 设置完毕后,我们使用 connectionFactory 的 newConnection 方法来创建出了一条链接,并返回我们连接 RabbitMQ 服务的 connection 信息。

在建立好连接之后,我们就可以向 RabbitMQ 中发送消息了,如下代码所示:

Channel channel = connection.createChannel();
String msg = "Hello RabbitMQ";
channel.basicPublish("", "test01", null, msg.getBytes());

现阶段,在上段代码中,我们只需要了解最后一行代码所表示的含义即可。

代码解释:

第 3 行,我们使用了 channel 的 basicPublish 方法来将我们定义的 msg 消息投递到 RabbitMQ 中,其中, basicPublish 方法的第一个参数表示交换机的名称,第二个参数表示路由 Key 的名称,第三个参数表示消息所设置的参数,第四个参数表示将我们的 msg 数据转换为 bytes 之后再进行投递。

通过上述代码,我们就实现了 RabbitMQ 的生产端,那消费端又该如何实现呢?

代码实现:

String queueName = "test01";
channel.queueDeclare(queueName, true, false, false, null);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel);
channel.basicConsume(queueName, true, defaultConsumer);

代码解释:

第 1 行,我们根据生产者声明的路由 Key ,定义了一个名为 queueName 的变量,来接收路由 Key 。

第 2 行,我们使用 channel 的 queueDeclare 方法,来声明一个名为 queueName 的队列。

第 3 行,我们对 RabbitMQ 中用来接收消息的 Consumer 进行初始化。

第 4 行,我们使用 channel 的 basicConsume 方法,来讲我们投递到 RabbitMQ 中的消息进行消费。

Tips 在这里,我们只是对 RabbitMQ 中如何实现生产端与消费端进行一个简单的了解,后续会进行深入介绍。

4.2 消息

定义:

消息,顾名思义,就是我们平常所说的一条信息、一条数据,消息是 RabbitMQ 中的核心元素,我们产生的任何数据,在 RabbitMQ 中都被称为消息。

在整个 RabbitMQ 工作流程中间,有且只有消息被流转,我们使用 RabbitMQ 的目的就是来处理我们应用程序中需要 RabbitMQ 来处理的任何消息,该消息可以是一句话,可以是一张图片,可以是一条视频,也可以是一种文档。

4.3 虚拟主机

定义:

虚拟主机,即 Virtual Host ,是用来存储 RabbitMQ 中所有消息数据的集合,每个 RabbitMQ 服务中默认只有一台虚拟主机,并且提供用户自定义虚拟主机的功能。

我们可以这样理解:RabbitMQ 中的每个虚拟主机都是一台数据库,在这个数据库中会存储 RabbitMQ 的交换机、频道、路由 Key ,以及消息队列,每一个虚拟主机是一个独立的单元,各虚拟主机之间不会相互干扰,各自完成各自的任务。

代码实现:

在 RabbitMQ 中,默认的虚拟主机为 “/” ,即如果我们不指定我们的虚拟主机,则所有的消息都会存储到名称为 “/” 的虚拟主机下,而我们如何使用虚拟主机呢?如下代码所示:

ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setVirtualHost("/");

代码解释:

第 2 行,我们使用 RabbitMQ 链接工厂的 setVirtualHost 方法,来为我们的链接指定一个虚拟主机,而指定的虚拟主机就是 RabbitMQ 所提供的默认虚拟主机。

Tips:
1. 一般来说,每一个应用程序或者每一个独立的业务模块,都会创建属于自己领域的虚拟主机,目的就是为了和其他业务模块分离开,同时,这样的架构模式更利于不同业务数据的统计与维护,在线上环境中,也更利于我们同学排查业务故障。
2. 如果你不知道你的应用程序该如何划分虚拟主机,那就请使用 RabbitMQ 自带的默认虚拟主机,这一点是很重要的。

4.4 交换机

定义:

交换机,即 exchange ,是传递消息的中间工具,我们可以把交换机理解为,传递消息的媒介,即我们发到 RabbitMQ 服务器中的消息,在经过虚拟主机之后,会首先到达 exchange 中,然后由 exchange 根据不同的匹配策略来将消息传递到对应的频道中去。

针对不同的业务场景,RabbitMQ 为我们内置了多种交换机供我们选择,这里只是对交换机的概念做一个简单的介绍,后续我们再详细介绍 RabbitMQ 中所有的交换机。

代码实现:

我们应该如何选择一种交换机呢?如下代码所示:

channel.exchangeDeclare("test_exchange", "direct");

代码解释:

第 1 行,我们使用了 channel 的 exchangeDeclare 方法,来选择了一种类型的交换机,该交换机类型为直接交换机,方法的第一个参数表示交换机的名称,我们可以根据实际情况自定义交换机名称,方法的第二个参数为交换机的类型,这个我们不可以自定义,必须要和 RabbitMQ 中所支持的交换机类型的名称保持一致才行。

4.5 路由 Key

定义:

路由 Key ,即 routing key ,交换机与频道之间进行绑定的 key ,通过这个 key ,可以实现消息由交换机转移至频道的过程,从而实现消息的流转。

在同一个虚拟主机中,不能存在相同路由 key 的 key 值。

代码实现:

我们应该如何定义 routing key 呢?如下代码所示:

channel.basicPublish("", "test_routing_key", null, msg.getBytes());

代码解释:

第 1 行,我们使用了 channel 的 basicPublish 方法,上述内容中已经对该方法进行了介绍,现在让我们直接来看该方法的第二个参数,第二个参数表示我们路由 key 的名称,这里为 test_routing_key 。

4.6 频道

定义:

频道,即 channel ,我们可以理解为传递消息的通道,在 RabbitMQ 中,消息最终经过 channel 发送给对应的消费者,消费者接收到消息并将该消息进行消费。

代码实现:

我们应该如何定义 channel 呢?如下代码所示:

ConnectionFactory connectionFactory = new ConnectionFactory();
// 省略连接 RabbitMQ 服务器的配置
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();

代码解释:

第 4 行,在由 ConnectionFactory 构建出一个连接后,我们使用了 connection 的 createChannel 方法来通过建立好的连接创建一个频道。

4.7 消息队列

定义:

消息队列,即消息所在的场所。在 RabbitMQ 中,不可能只存在一条消息,那么当存在多条消息时,RabbitMQ 会将这些消息组成一个队列,用来存放同一领域下的消息,这个队列就被称为消息队列。

当生成消息队列时,RabbitMQ 会根据不同的消息匹配策略,将不同领域的消息划分到对应的消息队列中去。消费者可以获取消息队列中的消息并消费,且我们可以通过设置一个阀值来规定我们同一时刻消费者需要消费的消息条数,这在高并发环境中是很重要的。

5. 小结

本小节详细介绍了 RabbitMQ 中的基础核心概念,包括消息、虚拟主机、交换机、路由 Key 、频道、消息队列、生产者、消费者,针对可以通过代码实现的基础核心概念,做了代码实现和代码解释,旨在帮助同学们在对理论知识有一定认知的同时,可以对相应概念的代码实现也有一个了解。

本小节是学习 RabbitMQ 的基础,在学习本节内容时,一定要理清楚本节中所涉及的所有的概念,同学们只有对这些概念有所了解之后,才能开始 RabbitMQ 的学习,各位同学加油。