初识RabbitMQ
初识RabbitMQ
- RabbitMQ安装和使用(docker,centos 7 )
- RabbitMQ的介绍
- RabbitMQ的作用
- RabbitMQ的基础知识
- 架构
- 交换机类型和路由规则
- SpringBoot整合RabbitMQ
RabbitMQ安装和使用(docker,centos 7 )
docker run \-e RABBITMQ_DEFAULT_USER=root \ -e RABBITMQ_DEFAULT_PASS=214913 \ - 指定用户名和密码,用于登录RabbitMQ-v mq-plugins:/plugins \ - 设置数据卷--name mq - 为容器指定名称为"mq"
--hostname mq - 设置容器的主机名为"mq",RabbitMQ推荐显式设置主机名以确保正确运行
-p 15672:15672 - 端口映射,将容器的15672端口(RabbitMQ管理界面)映射到宿主机的15672端口
-p 5672:5672 - 端口映射,将容器的5672端口(RabbitMQ AMQP协议端口)映射到宿主机的5672端口--network cc\ - 不存在不会创建,会报错-d \ - 以守护进程方式运行容器(后台运行)rabbitmq:3.8-management - 使用RabbitMQ 3.8版本镜像,并且包含管理插件
RabbitMQ管理界面的地址:ip:15672
这个貌似不需要开放虚拟机防火墙端口也可以访问(没试过),但是api端口需要开放。下面就是RabbitMQ的管理端页面,这里可以自己摸索一下。

RabbitMQ的介绍
RabbitMQ的作用
在一些场景下,比如用户支付,支付之后还需要修改订单状态,加积分,发通知,等一系列操作,如果我是同步调用,会引发一些问题。
- 性能低,支付业务逻辑处理完之后,还需要在进行其他业务,消耗时间。
- 耦合度高,如果加积分的代码修改了,可能支付业务这一块代码也需要修改
- 拓展性差,支付完之后,老板说在给客户来个京豆,优惠卷啥的,又要修改代码
如何解决呢,异步调用。
异步调用的模型结构:
- 发布者
- 消息代理(broker),也就是RabbitMQ的扮演的角色
- 消费者
具体流程就是:用户完成支付之后,支付的业务代码发送一条消息到RabbitMQ,消费者监听并处理RabbitMQ中的消息。
Broker的选择不只RabbitMQ一种,还有kafka,RocketMQ等。可以了解。
RabbitMQ的基础知识
架构
- 虚拟主机(virtualHost) :起到数据隔离的作用,就像java的模块,每一个虚拟主机都有自己的交换机和队列
- 交换机(exchange):生产者发送的消息由交换机决定投递到哪个队列
- 队列(queue):生产者投递的消息会暂存在消息队列中,等待消费者处理
- 生产者:发送消息的一方
- 消费者:消费消息的一方
交换机类型和路由规则
- Fanout Exchange (广播模式):会把接收到的消息广播到每一个跟其绑定的queue。
- Direct Exchange (定向路由): 把消息按照规则路由到指定的Queue,可以根据这种特性实现类似Fanout的效果。
○ 每一个Queue都与Exchange 设置一个BindingKey
○ 发布者发布消息时,指定消息的RoutingKey
○ Exchange将消息路由到BingdingKey和消息的RoutingKey一致的队列 - Topic交换机:和上一个类似。
a. routingKey可以是多个单词的列表,可以以 . 来分割
b. BingdingKey 可以使用通配符: # :代指0个或者是多个单词 * : 代指一个单词。
SpringBoot整合RabbitMQ
1.导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
2.yml文件配置
rabbitmq:port: 5672virtual-host: /mq # 虚拟机虚拟目录username: hh # 用户名password: 214913 # 密码listener: # 监听器配置simple:prefetch: 1 # 每次只处理一个消息publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型publisher-returns: true # 开启publisher return机制
3.使用注解来声明交换机和队列
@RabbitListener(// 绑定队列到交换机bindings = @QueueBinding(// 队列配置 ,durable = true 表示持久化value = @Queue(value = "petlife.board.queue",name = "petlife.board.queue",arguments = @Argument(name = "x-queue-mode", value = "lazy"),// x-queue-mode: 队列模式,lazy 懒加载,表示队列中的消息会存储在磁盘中,而不是内存中//value: 指定队列在 RabbitMQ 中的实际名称//name: 指定队列在 Spring 容器中的 Bean 名称durable = "true"),// 交换机配置,exchange = @Exchange(value = "petlife.board.exchange", // 交换机名称type = ExchangeTypes.TOPIC), // 交换机类型,topic 交换机key = "board.#")) // 路由键,匹配 board. 开头的路由键public void listener(String message) {//执行具体的业务逻辑System.out.println("监听到消息:" + message);}
4.声明消息转换器(默认是jdk自带的序列化方式,不过springboot好像指定的是Jackson2JsonMessageConverter,没验证过,有时间试试)
@SpringBootApplication
@ComponentScan(basePackages = {"com.petlife"})
public class PetLifeApplication {public static void main(String[] args) {SpringApplication.run(PetLifeApplication.class, args);}@Beanpublic MessageConverter messageConverter(){// 1.定义消息转换器 : springboot默认使用JDK序列化,这里使用Jackson2JsonMessageConverterJackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();// 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息jackson2JsonMessageConverter.setCreateMessageIds(true);return jackson2JsonMessageConverter;}}
。。。。 未完待续
