RabbitMQ入门

简介: RabbitMQ是基于Erlang开发的开源消息中间件,支持AMQP协议,实现应用间解耦与异步通信。其核心组件包括生产者、消费者、队列、交换机和虚拟主机,可通过Docker快速部署并结合SpringAMQP实现消息收发。

2.1 RabbitMQ介绍

RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址:https://www.rabbitmq.com/

RabbitMQ的架构如图:

其中包含几个概念:

  • publisher:生产者,也就是发送消息的应用程序
  • consumer:消费者,也就是消费消息的应用程序
  • queue:队列,存储消息的缓冲区。生产者投递的消息会暂存在消息队列中,等待消费者处理
  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue

上述这些东西都可以在RabbitMQ的管理控制台来管理,下一节我们就一起来学习控制台的使用。

2.2. 安装

已帮大家装好mq,但是这里面有很多冗余的数据,你可以直接启动

  • docker ps -a:查看所有,可以看到有单机mq,和集群的mq1~3
  • docker start mq启动即可

或先删除【建议】

  • docker rm -f mq
  • 然后执行下面的启动脚本即可

或启动时候,命名一个新的

docker run \

-e RABBITMQ_DEFAULT_USER=itheima \

-e RABBITMQ_DEFAULT_PASS=123321 \

-v mq-plugins:/plugins \

--name mq197 \

-p 15672:15672 \

-p 5672:5672 \

-d \

rabbitmq:3.8-management

我们同样基于Docker来安装RabbitMQ,使用下面的命令即可:

找到课前资料下的mq.tar(rabbitmq的镜像文件),上传到/root下。

利用docker load命令加载:docker load -i mq.tar

执行下边的脚本创建容器:

docker run \
 -e RABBITMQ_DEFAULT_USER=itheima \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3.8-management

可以看到在安装命令中有两个映射的端口:

  • 15672:RabbitMQ提供的管理控制台的端口
  • 5672:RabbitMQ的消息发送处理接口

安装完成后,我们访问 http://192.168.101.68:15672 即可看到管理控制台。首次访问需要登录,默认的用户名:itheima,密码:123321。登录后即可看到管理控制台总览页面:

2.3. 收发消息

2.3.1 搭建环境

RabbitMQ安装成功后下边我们编写消息发送与消息接收程序实现收发消息,如下图:publisher即消息发送者将消息发送到MQ的队列中,consumer即消息消费者从MQ中接收消息。

RabbitMQ通信采用了AMQP (Advanced Message Queuing Protocol) 协议,因此它具备跨语言的特性,任何语言只要遵循AMQP协议都可以使用RabbitMQ收发消息。

RabbitMQ官方也提供了各种不同语言的客户端API,RabbitMQ官方提供的Java客户端编码相对复杂,一般生产环境下我们更多会结合Spring来使用。而Spring的官方刚好基于RabbitMQ提供了这样一套消息收发的模板工具:SpringAMQP。并且还基于SpringBoot对其实现了自动装配,使用起来非常方便。

SpringAmqp的官方地址:https://spring.io/projects/spring-amqp

SpringAMQP提供了三个功能:

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

下边使用SpringAMQP实现消息收发,上图是RabbitMQ最简单的工作模型,我们仅作测试使用,这种模式一般很少在生产中使用。

在课前资料给大家提供了一个Demo工程,方便我们学习SpringAMQP的使用:

将其复制到你的工作空间,然后用Idea打开,项目结构如图:

包括三部分:

  • mq-demo:父工程,管理项目依赖
  • publisher:消息的发送者
  • consumer:消息的消费者

在mq-demo这个父工程中,已经配置好了SpringAMQP相关的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.itcast.demo</groupId>
  <artifactId>mq-demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>publisher</module>
    <module>consumer</module>
  </modules>
  <packaging>pom</packaging>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath/>
  </parent>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <!--AMQP依赖,包含RabbitMQ-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <!--单元测试-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
  </dependencies>
</project>

设置java版本

因此,子工程中就可以直接使用SpringAMQP了。

2.3.2 创建队列

首先进入RabbitMQ控制台创建队列,新建一个队列:simple.queue

添加成功:

接下来,我们就可以利用Java代码收发消息了。

2.3.3 消息发送

首先配置MQ地址,在publisher服务的application.yml中添加配置:

spring:
  rabbitmq:
    host: 192.168.101.68 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: itheima # 用户名
    password: 123321 # 密码

然后在publisher服务的test下编写测试类SpringAmqpTest,并利用RabbitTemplate实现消息发送:

package com.itheima.publisher.amqp;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@Slf4j
public class SpringAmqpTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Test
    public void testSimpleQueue() {
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, spring amqp!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
        log.info("消息发送成功:{}",message);
    }
}

打开控制台,可以看到消息已经发送到队列中:

接下来,我们再来实现消息接收。

我们可以在RabbitMQ的控制台去查看消息

2.3.4 消息接收

首先配置MQ地址,在consumer服务的application.yml中添加配置:

spring:
  rabbitmq:
    host: 192.168.101.68 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: itheima # 用户名
    password: 123321 # 密码

然后在consumer服务的com.itheima.consumer.listener包中新建一个类SpringRabbitListener,代码如下:

package com.itheima.consumer.listener;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class SpringRabbitListener {
    // 利用RabbitListener来声明要监听的队列信息
    // 将来一旦监听的队列中有了消息,就会推送给当前服务,调用当前方法,处理消息。
    // 可以看到方法体中接收的就是消息体的内容
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueMessage(String msg) throws InterruptedException {
        System.out.println("spring 消费者接收到消息:【" + msg + "】");
    }
}

2.3.5 测试

测试流程:

  • 启动consumer服务
  • 在publisher服务中运行测试代码,发送MQ消息。
  • 观察consumer控制台日志收到消息:

2.3.6 推模式与拉模式

在RabbitMQ中,消息传递给消费者的方式有两种:推模式(Push)和拉模式(Pull)。

  1. 推模式(Push):这是最常用的模式,在这种模式下,一旦消费者订阅了一个队列,RabbitMQ就会自动将队列中的消息发送给消费者,这种方式不需要消费者持续地询问是否有新的消息,而是由Broker在有消息时主动发送给消费者。
  2. 拉模式(Pull):在这种模式下,消费者需要主动请求Broker来获取消息。

在实践中,推模式更常见,因为它可以减少消费者的网络负载,并且可以让Broker更好地控制消息的传递速率。然而,拉模式也有其应用场景,比如当消费者想要精确控制消息获取的时候。

RabbitMQ默认采用的是推模式,但同时也提供了拉模式的支持,以满足不同的应用场景需求。

2.4. 数据隔离

2.4.1 用户管理

RabbitMQ支持多租户,多个系统可以同时使用一个RabbitMQ。

什么是多租户一种软件架构设计模式,允许多个租户(用户、组织或客户)共享同一套应用程序或系统实例,同时确保每个租户的数据和配置是隔离的。比如一张表增加一个companyId,那么就是不同的公司共用一套代码+数据库,但是又做了数据隔离

公司内的多个不同项目同时使用。这个时候为了避免互相干扰, 我们会利用虚拟主机进行隔离,将不同项目隶属不同的虚拟主机。一般会做两件事情:

  • 给每个项目创建独立的运维账号,将管理权限分离。
  • 给每个项目创建不同的虚拟主机,将每个项目的数据隔离。

下边学习用户管理和虚拟主机的配置。

点击Admin选项卡,首先会看到RabbitMQ控制台的用户管理界面:

这里的用户都是RabbitMQ的管理或运维人员。目前只有安装RabbitMQ时添加的itheima这个用户。仔细观察用户表格中的字段,如下:

  • Nameitheima,也就是用户名
  • Tagsadministrator,说明itheima用户是超级管理员,拥有所有权限
  • Can access virtual host/,可以访问的virtual host,这里的/是默认的virtual host

下边我们给黑马商城创建一个新的用户,命名为hmall,密码123,注意选择adminstrator

你会发现此时hmall用户没有任何virtual host的访问权限:

接下来我们来给hmall用户授权。

2.4.2 虚拟主机

下边配置虚拟主机。

我们先退出登录:

切换到刚刚创建的hmall用户登录,然后点击Virtual Hosts菜单,进入virtual host管理页:

可以看到目前只有一个默认的virtual host,名字为 /

我们可以给黑马商城项目创建一个单独的virtual host,而不是使用默认的/

创建完成后如图:

由于我们是登录hmall账户后创建的virtual host,因此回到users菜单,你会发现当前用户已经具备了对/hmall这个virtual host的访问权限了:

此时,点击页面右上角的virtual host下拉菜单,切换virtual host/hmall

然后再次查看queues选项卡,会发现之前的队列已经看不到了:

这就是基于virtual host 的隔离效果。

2.4.3 测试

下边我们用hmall用户及新创建虚拟主机。

修改publisher及consumer的application.yml

spring:
  rabbitmq:
    host: 192.168.101.68 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: /hmall # 虚拟主机
    username: hmall # 用户名
    password: 123 # 密码

重新进行收发消息的测试,发现消息发发放到了virtual-host: /hmall 下的队列,如下图:

再启动consumer服务接收消息。

3 RabbitMQ工作模型

相关文章
|
消息中间件 存储 Cloud Native
揭秘发布订阅模式:让消息传递更高效
揭秘发布订阅模式:让消息传递更高效
揭秘发布订阅模式:让消息传递更高效
|
NoSQL 关系型数据库 MySQL
如何向mongoDB中添加新的字段附代码(全)
关于MongoDB更多的知识点可看我之前这篇文章: MongoDB框架零基础入门本身MongoDB的连接就和Mysql的数据库一样 Mysql连接方式:mysql -u -root -p(标准模式下) MongoDB类似:mongo -u root -p之所以要增加字段值 一般都是python web框架中,在form表单内增加了一个字段值写入数据库(只有最新的数据才有这个字段值) 之前数据没有的字段值只能通过数据库添加 具体添加方式可以通过数据库内或者脚本一键添加(两种方式都差不多)在数据库内增加字段值
907 0
|
JavaScript 前端开发
addEventListener()方法中的参数,以及作用
addEventListener()方法中的参数,以及作用
592 1
|
JavaScript 前端开发
解释 JavaScript 中的`map()`、`filter()`和`reduce()`方法的用途。
解释 JavaScript 中的`map()`、`filter()`和`reduce()`方法的用途。
381 1
|
Java 数据库连接 Spring
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
1934 0
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
|
5月前
|
Cloud Native Java API
Spring Boot 3.0 vs. 2.0
Spring Boot 3.0 带来革命性升级:全面支持 Java 17+ 与 Jakarta EE,引入原生编译、增强可观测性,推动云原生转型。相比 2.0,性能更强、启动更快、更现代。新项目应首选 3.0,老项目需逐步迁移,拥抱未来。
|
SQL 监控 关系型数据库
使用SQL语句查询操作耗时的技巧与方法
在数据库管理和优化过程中,了解SQL查询操作的耗时是至关重要的
1951 0
|
JavaScript 前端开发
多种模块格式,包括 ES, CommonJS, UMD, AMD, SystemJS 和 IIFE的区别点分别是什么?
【10月更文挑战第20天】在实际应用中,选择合适的模块格式需要根据项目的需求、目标环境以及开发团队的习惯等因素来综合考虑。不同的模块格式都有其自身的优势和适用场景,合理选择可以提高代码的组织性、可维护性和性能。
594 8
|
JavaScript 前端开发
JS中的事件监听
JS中的事件监听
270 4
|
JavaScript 监控 编译器
29.【TypeScript 教程】装饰器(Decorator)
29.【TypeScript 教程】装饰器(Decorator)
241 0