在上一篇文章中我们讲到了如何在Windows中安装Rabbitmq, 小白也能搞定!手把手教你在 Windows 上安装 RabbitMQ 我们先安装了Erlang环境,之后又安装了Rabbitmq,最后我们通过安装Rabbitmq的web管理端成功验证了,但是相信大家进入Rabbitmq的管理页面都和作者一样傻眼了,这么多的页签,这都什么意思啊???
所以这次我们来结合代码和页面对应的功能来入门一下Rabbitmq的基础名词和他们的概念。
在说Rabbitmq之前,我们需要了解一下什么是消息队列?
消息队列(Message Queue, MQ)是一种软件设计模式,也是一种中间件技术,它允许应用程序通过网络进行异步通信。在消息队列中,消息被发送到队列中,接收端(消费者)可以从队列中取出这些消息进行处理。消息队列的设计目的是为了实现异步处理、解耦服务以及提升系统的可扩展性和健壮性。
消息队列(Message Queue, MQ)是一种应用程序间的通信方法,它允许多个组件之间通过异步方式传递数据。消息队列的主要目的是解耦系统组件,提高系统的可扩展性和健壮性。在消息队列中,生产者发送消息,消费者接收消息,中间件(通常是消息队列服务)负责存储和转发消息。
那他在我们工作中应该怎么用呢?
假设我们正在开发一个电子商务网站,当用户提交订单时,前端向订单服务发送一个请求,订单服务创建订单并将相关信息(例如订单号、商品信息等)放入消息队列。然后,订单服务立即返回给前端,告诉用户订单已提交。此时,后台的订单处理服务从消息队列中读取新订单的消息并开始处理订单,如检查库存、扣减库存、计算运费等。
这种方式的好处是,订单服务可以立即响应用户,而无需等待耗时的操作完成,从而提高了用户体验。同时,如果订单处理服务暂时不可用或者处理速度较慢,也不会影响到用户的即时体验。
好了,这下简洁明了的介绍了一下MQ,那么我们来认识一下Rabbitmq。
RabbitMQ 是一个在分布式系统中实现消息传递的应用程序,它基于 AMQP(Advanced Message Queuing Protocol,高级消息队列协议)标准。RabbitMQ 由 LShift 和 NetBM 公司在 2007 年开发,并于 2010 年被 Pivotal 软件公司收购。它是用 Erlang 语言编写的,这使得它非常擅长处理大量的并发连接。市面上有很多的MQ产品,例如kafka,RocketMQ等,而Rabbitmq也是MQ系列产品中的一个产品。
认识Rabbitmq基础模式:
在最新的版本中Rabbitmq有七种模式
-
"Hello World!":
- 生产者发送一条消息到队列,消费者接收并处理这条消息。
-
Work Queues:
- 多个消费者竞争从队列中取出并处理任务消息。
-
Publish/Subscribe (Pub/Sub):
- 生产者发送消息到交换器,所有订阅该交换器的消费者都会接收到消息。
-
Routing:
- 生产者发送带有 routing key 的消息,只有绑定对应 routing key 的队列中的消费者才能接收到消息。这类似于精确匹配(等于)routing key
-
Topics:
- 生产者发送消息,消费者根据订阅的 routing key 模式接收消息。这类似于使用通配符进行模式匹配(类似于 SQL 中的
LIKE
)
- 生产者发送消息,消费者根据订阅的 routing key 模式接收消息。这类似于使用通配符进行模式匹配(类似于 SQL 中的
-
RPC (Remote Procedure Call):
- 客户端发送请求消息,服务端处理后返回响应。
-
Publisher Confirms:
- 生产者发送消息后等待 RabbitMQ 的确认,以确保消息已被成功接收。
好了,说了这么多,可以介绍一下web管理端了
RabbitMQ 的 Web 管理界面提供了丰富的工具来监控和管理 RabbitMQ 服务器的状态和配置。
Overview
- 简介:提供了 RabbitMQ 服务器的整体概览,包括节点状态、内存使用情况、队列数量、连接数、通道数等关键指标。
- 用途:帮助管理员快速了解 RabbitMQ 的运行状态和整体健康状况。
Totals
如果我们使用sdk发送一条消息的话:
java
@Test
public void testSend() throws Exception {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置主机
connectionFactory.setHost("127.0.0.1");
//设置端口
connectionFactory.setPort(5672);
//设置连接的虚拟主机
connectionFactory.setVirtualHost("/local");
//设置用户名和密码
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接对象
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定消息队列
channel.queueDeclare("test-send", false, false, false, null);
//发部消息
channel.basicPublish("", "test-send", null, "hello rabbitmq".getBytes());
channel.close();
connection.close();
}
我们就会在Totals下的Message rates和Queued messages的仪表盘中看到一条曲线。
Message Rates
消息的发送速率(publish rate)和消费速率(deliver rate),帮助管理员了解当前系统的消息吞吐量,并评估系统的性能和负载情况。
-
Publish
每秒发布的消息数量。这反映了生产者向 RabbitMQ 发送消息的速度。
-
Publisher Confirm 每秒确认的消息数量。这反映了生产者收到的消息确认速度,确保消息已被 RabbitMQ 成功接收。
-
Deliver (manual ack)
每秒手动确认交付给消费者的非自动确认消息数量。这反映了消费者从 RabbitMQ 接收并需要手动确认的消息速度
-
Deliver (auto ack)
每秒自动确认交付给消费者的自动确认消息数量。这反映了消费者从 RabbitMQ 接收并自动确认的消息速度。
-
Consumer Ack
每秒由消费者确认的消息数量。这反映了消费者处理并确认消息的速度。
-
Redelivered
每秒重新交付给消费者的未确认消息数量。这反映了由于消费者未确认而导致重新发送的消息数量。
-
Get (manual ack)
每秒通过
get
命令手动确认的消息数量。这反映了通过get
API 方法获取并需要手动确认的消息速度。 -
Get (auto ack)
每秒通过
get
命令自动确认的消息数量。这反映了通过get
API 方法获取并自动确认的消息速度。 -
Get (empty)
每秒通过
get
命令尝试获取消息但队列为空的次数。这反映了尝试从空队列中获取消息的频率。 -
Unroutable (return)
每秒因无法路由而被返回给生产者的消息数量。这反映了无法被正确路由的消息数量。
-
Unroutable (drop)
每秒因无法路由而被丢弃的消息数量。这反映了无法被正确路由并被丢弃的消息数量。
Queued Messages
当前队列中等待处理的消息总数,帮助管理员了解队列中积压的消息量,并判断系统是否存在消息积压问题及积压程度。
- Ready:当前队列中有几条消息准备好被消费者消费。
- Unacked:当前消息被消费者获取后还未确认的数量。
- Total:当前队列中总共有几条消息。
这个页面下后面的配置项就不做过多介绍,包括:
Nodes
- 显示当前 RabbitMQ 集群中所有节点的状态信息,帮助监控每个节点的运行状况。
Churn Statistics
- 提供集群中节点加入和离开的统计信息,反映集群的稳定性。
Ports and Contexts
- 展示 RabbitMQ 服务器使用的端口和上下文信息,帮助管理和配置网络设置。
Export Definitions
- 允许导出当前配置到文件,方便备份或迁移配置。
Import Definitions
- 允许从文件导入配置,方便恢复或迁移配置到另一个环境。
Connections
- 简介:显示当前所有活动的连接及其详细信息,如连接 ID、用户名、来源 IP 地址、状态等。
- 用途:便于监控和管理客户端与 RabbitMQ 服务器之间的连接,识别潜在的问题连接。
我们把上面发送消息的代码改造一下,让他在关闭之前线程睡一下,我们就可以发现有一个Connection连接:
java
@Test
public void testSend() throws Exception {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置主机
connectionFactory.setHost("127.0.0.1");
//设置端口
connectionFactory.setPort(5672);
//设置连接的虚拟主机
connectionFactory.setVirtualHost("/local");
//设置用户名和密码
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接对象
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定消息队列
channel.queueDeclare("test-send", false, false, false, null);
//发部消息
channel.basicPublish("", "test-send", null, "hello rabbitmq".getBytes());
Thread.sleep(100000);
channel.close();
connection.close();
}
所以这里主要的代码就是这里:
ini
//获取连接对象
Connection connection = connectionFactory.newConnection();
通过这个我们就可以在管理端看到对应的连接了
name的tab点击进来后就可以看到我们连接的具体信息了:
包含了一个连接的详细信息,包括连接名称、数据传输速率、连接细节、通道列表和客户端属性
Channels
- 简介:展示当前所有活动的通道及其相关信息,如通道 ID、所属连接、状态等。
- 用途:用于监控和管理客户端与 RabbitMQ 之间的通信通道,确保消息传递的正常运作。
而这里就是因为上面的这行代码:
ini
//获取连接通道
Channel channel = connection.createChannel();
点击Channel的tab标签也可以看到详细信息
包含了某个特定通道的详细信息,包括消息速率、通道状态、未确认的消息数、消费者数量和高级运行时指标。
在 RabbitMQ 中,连接(Connection)和通道(Channel)之间存在着密切的关系。连接是客户端与 RabbitMQ 服务器之间的物理通信路径,而通道是在连接之上建立的逻辑信道,用于执行各种操作,如发布消息、订阅队列等。
一个连接可以同时打开多个通道,每个通道都有自己的生命周期,独立于其他通道。多个通道共享同一个连接的资源,如心跳检测和认证信息。不同通道之间的操作相互隔离,不会互相影响。
Exchanges
- 简介:列出所有已定义的交换器及其配置,包括类型、持久性、自动删除等属性。
- 用途:管理消息的路由规则,查看和配置交换器,确保消息能够正确地路由到目标队列。
交换机(Exchange)是一个消息分发中心,它接收生产者发布的消息并根据预设的规则将其转发到适当的队列。
可以看到rabbitmq中默认有七个交换机,他们的作用分别是:
(AMQP default)
: 默认交换机,用于 AMQP 协议的基本功能。amq.direct
: 直接交换机,用于简单的一对一消息传递。amq.fanout
: 扇出交换机,用于广播消息给所有绑定的队列。amq.headers
: 基于消息头进行路由的交换机。amq.match
: 匹配所有条件的交换机。amq.rabbitmq.trace
: 用于发送 RabbitMQ 内部跟踪消息的交换机。amq.topic
: 主题交换机,支持模式匹配。
这些交换机在 RabbitMQ 中已经预置好,用户可以直接使用,也可以根据需要创建自己的交换机。
具体什么是交换机,我们说我队列再讲。
Queues
- 简介:显示所有已声明的队列及其状态信息,如消息数量、未确认消息数、消费者数量等。
- 用途:监控队列的状态,确保消息能够正确地存储和被消费者处理。
队列,这是MQ最核心的一个机制了,而这也是我们的这一行代码创建的:
csharp
//通道绑定消息队列
channel.queueDeclare("test-send", false, false, false, null);
声明队列
queue -- 队列的名称
durable -- 如果我们声明一个持久队列,则为 true(队列将在服务器重启后继续存在)
exclusive -- 如果我们声明一个独占队列(仅限于此连接),则为 true。
autoDelete -- 如果我们声明一个 autodelete 队列,则为 true(服务器将在不再使用时将其删除)
arguments -- 队列的其他属性(构造参数)
而点进name标签我们可以看到下面的信息:
而这个界面也是我们开发过程中最频繁打开的页面了,这里可以看到队列里面的总的消息,没确认的消息,以及队列的情况,等等,例如:
- Features: 队列的特性,如是否持久化、是否有消费者等。
- State: 队列的状态,这里是 "idle",表示没有活动的消费者。
- Messages: 队列中的消息总数、准备就绪的消息数、未确认的消息数、内存中的消息数、持久化的消息数以及分页外的消息数。
- Consumer utilisation: 消费者利用率,目前为 0%。
- Message body bytes: 消息体的字节大小。
- Process memory: 队列占用的进程内存大小。
以及Consumers:哪些消费者连接到了这个队列。例如我们使用sdk监听这个队列:
java
package com.masiyi.springbootrabbitmq;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
public class Consumer {
public static void main(String[] args) throws Exception {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置主机
connectionFactory.setHost("127.0.0.1");
//设置端口
connectionFactory.setPort(5672);
//设置连接的虚拟主机
connectionFactory.setVirtualHost("/local");
//设置用户名和密码
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接对象
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定消息队列
channel.queueDeclare("test-send", false, false, false, null);
channel.basicConsume("test-send", true, new DefaultConsumer(channel) {
/**
* @param body 接受到的消息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
//如果想一直监听就不要关闭通道
// channel.close();
// connection.close();
}
}
可以看到我们里面的6条消息瞬间就被消费掉了
而我们的页面也会变成这样:
我们可以看到消费者具体的情况
Admin
- 简介:提供了一系列高级管理功能,如用户管理、权限配置、节点配置等。
- 用途:用于配置 RabbitMQ 的高级设置,包括用户账号、权限分配、集群配置等,确保 RabbitMQ 的安全性和可配置性。
这块主要显示的是跟账号有关的内容,点击Name的页签,可以看到guest用户具体的信息,可以改权限,设置密码,删除用户啥的
而在下面的添加用户功能则可以添加新的用户
但是大家有没有注意到右上角有一个Virtual host选项,虚拟主机(Virtual Host)是一种逻辑隔离机制,它可以让你在一个 RabbitMQ 实例中同时运行多个独立的应用程序或服务。虚拟主机允许你将相关联的交换机、队列和绑定组合在一起,形成一个逻辑单元,从而实现多租户环境。每个虚拟主机有自己的权限设置,因此不同虚拟主机内的实体彼此隔离,避免相互影响。
而我们在连接到 RabbitMQ 服务器的客户端时,必须指定要使用的虚拟主机。例如我们的代码在这里就会指定虚拟机
arduino
//设置连接的虚拟主机
connectionFactory.setVirtualHost("/local");
他们之间的关联
在页面上我们都介绍完他们的作用了,那么我们看到的东西:Connection、Channel、Virtual Host、Exchange 和 Queue 他们之间的作用和关系是什么样的呢?
-
Connection:连接是指客户端(发送或接收消息的应用程序)与 RabbitMQ 服务器之间的物理连接。通常,一个应用程序会创建一个或多个连接来与 RabbitMQ 进行交互。连接是 TCP 连接,负责在客户端和服务器之间传输数据。
-
Channel:通道是在连接之上建立的逻辑信道,用于执行实际的操作,如发布消息、订阅队列等。通道是轻量级的,比连接更高效,而且可以复用连接。大多数 RabbitMQ 操作都是通过通道完成的。
-
Virtual Host:虚拟主机是一种逻辑隔离,它将一组交换机、队列和绑定组成一个集合,使得多个应用程序可以在同一台 RabbitMQ 服务器上运行而不会互相干扰。每个连接都需要指定一个虚拟主机,这样它就能访问相应的交换机和队列。
-
Exchange:交换机是消息路由的核心组件。它接收来自生产者的消息,并根据预先定义的路由规则将消息转发到一个或多个队列。交换机有多种类型,如 direct、fanout、topic 和 headers,每种类型都对应着不同的路由策略。
-
Queue:队列是消息的容器,用来存储消息直到消费者将其取走。队列是无序的,一次只有一个消费者可以读取消息。队列可以是持久性的,即使 RabbitMQ 服务器重启也能保留消息。
emem。。。我相信大家已经听蒙了,下面给大家举一个例子:如果大家熟悉 MySQL 数据库,那么可以将 RabbitMQ 中的 Connection、Channel、Virtual Host、Exchange 和 Queue 类比作以下数据库概念:
- Connection:类似于数据库连接(Database Connection),它是客户端与数据库服务器之间的物理连接,用于发送 SQL 查询和接收响应。
- Channel:类似于数据库事务(Transaction),它是一组操作的逻辑单位,在一个事务中执行的所有操作要么全部成功,要么全部失败。在 RabbitMQ 中,通道也是轻量级的,用于执行一系列操作,如发送和接收消息。
- Virtual Host:类似于数据库中的数据库(Database),它是一个逻辑隔离的集合,包含了多个表(Queue)和视图(Exchange)。每个数据库都有自己的用户权限和设置。
- Exchange:类似于数据库中的视图(View),它根据预定义的规则展示数据,但并不存储数据本身。在 RabbitMQ 中,交换机接收消息并根据路由规则将消息转发到一个或多个队列。
- Queue:类似于数据库中的表(Table),它存储了数据记录。队列存储消息,等待消费者来读取消息。
至此,我们知道了rabbitmq的web管理端的相关页面的操作,也结合代码讲了rabbitmq的核心名词,相信大家对rabbitmq已经有个概念了。