目录
什么是RabbitMQ
RabbitMQ特征
下载软件
配置Erlang的环境变量
RabbitMQ的结构
利用RabbitMQ完成消息的收发
接收RabbitMQ中的消息
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。 RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
1.可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
2.灵活的路由(Flexible Routing) 在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
3.消息集群(Clustering) 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker
4.高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
5.多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。
6.多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
7.管理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。
8.跟踪机制(Tracing) 如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。
9.插件机制(Plugin System) RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
RabbitMQ是Erlang语言开发的,所以要先安装Erlang语言的运行环境
下载Erlang的官方路径
OTP Versions Tree
安装的话就是双击
安装过程中都可以使用默认设置,需要注意的是
不要安装在中文路径和有空格的路径下!!!
下载RabbitMQ的官方网址
Installing on Windows — RabbitMQ
安装也是双击即可
不要安装在中文路径和有空格的路径下!!!
要想运行RabbitMQ必须保证系统有Erlang的环境变量
配置Erlang环境变量
把安装Erlang的bin目录配置在环境变量Path的属性中
启动RabbitMQ
找到RabbitMQ的安装目录
可能是:
D:\tools\rabbit\rabbitmq_server-3.10.1\sbin
具体路径根据自己的情况寻找
地址栏运行cmd
输入启动指令如下
D:\tools\rabbit\rabbitmq_server-3.10.1\sbin>rabbitmq-plugins enable rabbitmq_management
结果如下
运行完成后,验证启动状态
RabbitMQ自带一个管理的界面,所以我们可以访问这个界面来验证它的运行状态
http://localhost:15672
登录界面用户名密码
guest
guest
登录成功后看到RabbitMQ运行的状态
如果启动失败,可以手动启动RabbitMQ
参考路径如下
微服务17-RabbitMQ的下载和报错及解决方案_teyruthy的博客-CSDN博客
RabbitMQ软件支持很多种消息队列的发送方式的
使用的比较多的是路由模式
和Kafka不同,Kafka是使用话题名称来收发信息,结构简单
RabbitMQ是使用交换机\路由key指定要发送消息的队列
消息的发送者发送消息时,需要指定交换机和路由key名称
消息的接收方接收消息时,只需要指定队列的名称
在编写代码上,相比于Kafka,每个业务要编写一个配置类
这个配置类中要绑定交换机和路由key的关系,以及路由Key和队列的关系
csmall-stock-webapi项目中测试RabbitMQ
可以利用之前我们使用Quartz实现的每隔一段时间输出当前日期信息的方法改为发送消息
添加依赖
org.springframework.boot
spring-boot-starter-amqp
yml文件配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
# 设置虚拟host 单机模式下固定编写"/"即可
virtual-host: /
交换机\路由Key\队列的配置类
RabbitMQ要求我们在java代码级别设置交换机\路由Key\队列的关系
我们在quartz包下,创建config包
包中创建配置信息类RabbitMQConfig
// 当前类配置RabbitMQ中交换机,路由Key和队列的关系
// 交换机和队列是实际对象,而路由Key只是绑定关系,他们都需要保存到Spring容器中来管理
@Configuration
public class RabbitMQConfig {
// 需要将使用到的交换机\路由Key\队列的名称使用常量定义出来
public static final String STOCK_EX="stock_ex";
public static final String STOCK_ROUT="stock_rout";
public static final String STOCK_QUEUE="stock_queue";
// 先声明交换机对象,保存到Spring容器
// 根据实际需求保存交换机的数量
@Bean
public DirectExchange stockDirectExchange(){
return new DirectExchange(STOCK_EX);
}
// 再声明队列对象,保存到Spring容器
@Bean
public Queue stockQueue(){
return new Queue(STOCK_QUEUE);
}
// 最后声明路由Key,注意路由Key是一种关系对象,不会单独将对象保存到Spring容器中
// 主要是关联哪个交换机绑定了哪个队列
@Bean
public Binding stockBinding(){
return BindingBuilder.bind(
stockQueue()).to(stockDirectExchange()).with(STOCK_ROUT);
}
}
RabbitMQ发送消息
我们在QuartzJob类中输出时间的代码后继续编写代码
实现RabbitMQ消息的发送
public class QuartzJob implements Job {
// 向RabbitMQ发送消息
// 也是从Spring容器中获取SpringBoot启动时为我们创建好的对象
@Autowired
private RabbitTemplate rabbitTemplate;
int i=1;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 实现一个简单的任务用作演示
// 例如输出当前系统时间
System.out.println("-------------------"+ LocalDateTime.now()
+"---------------------");
// 实例化一个Stock对象
Stock stock=new Stock();
stock.setId(i++);
stock.setCommodityCode("PC100");
stock.setReduceCount(RandomUtils.nextInt(100));
// 利用RabbitMQTemplate发送消息
// convertAndSend([交换机名称],[路由Key名称],[要发送的消息])
rabbitTemplate.convertAndSend(
RabbitMQConfig.STOCK_EX,
RabbitMQConfig.STOCK_ROUT,
stock);
System.out.println("发送消息完成:"+stock);
}
}
我们可以通过修改QuartzConfig类中的Cron表达式修改调用的周期
CronScheduleBuilder cron=
CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
按上面的cron修改之后,会每隔10秒运行一次发送消息的操作
启动服务,观察是否每隔10秒发送异常消息
启动Nacos\RabbitMQ\Seata
启动stock-webapi
根据Cron表达式,消息会在0/10/20/30/40/50秒数时运行
quartz包下再创建一个新的类用于接收信息
RabbitMQConsumer代码如下
// 当前接收消息的类,也要保存到Spring容器中
@Component
// 和Kafka不同,RabbitMQ的监听器注解要写到类上
@RabbitListener(queues = {RabbitMQConfig.STOCK_QUEUE})
public class RabbitMQConsumer {
// 在类上标记监听器注解,但是不能标记对哪个方法运行
// 所以我们需要在要执行消息处理的方法前添加另外的注解
// 每个类只允许一个方法标记这个注解
// 方法参数比Kafka更简单,直接声明接收消息的类型参数即可
@RabbitHandler
public void process(Stock stock){
System.out.println("消息接收完成!内容是:"+stock);
}
}
启动Nacos\RabbitMQ\Seata
启动stock-webapi
会在0/10/20/30/40/50秒时发送消息
消息的接收会实时运行