1、简介
使用场景
(1)异步处理
- 注册——》发短信——》发邮件——》收到响应
- 注册——》同时发短信邮件——》收到响应
- 注册——》写入消息队列——》收到响应——》异步读取发送短信邮件(异步处理)
(2)应用解耦
- 订单——》库存
- 订单——》消息队列《——库存
(3)流量削峰
秒杀数量为1w,当消息队列请求达到1w之后,用户请求直接返回秒杀失败,之后进行业务处理。
- 用户请求——》消息队列——》业务处理
概念
(1)消息代理:message broker,中间服务器;
(2)目的地:destination,服务器要发送消息的目的地;
消息队列有两种形式目的地:
- 队列:点对点消息通信
消息只有唯一发送者,但是可以由ABC等多个接受者,但是只能由其中一个接收。 - 主题:发布/订阅消息通信
发送者发送消息后,多个接收者只要订阅这个主题,就可以同时收到。
常见消息队列规范
(1)JMS:Java消息服务,基于jvm消息代理的规范;
(2)AMQP:高级消息队列协议,也是一个消息队列规范,兼容JMS;
2、中间件:RabbitMQ
(1)RabbitMQ是一个由erlang开发的AMQP的开源实现。
(2)核心概念
- Message:
消息,由消息头和消息体组成。消息体是不透明的,而消息头则由一些列的可选属性组成,这些属性包括路由键(routing-key)、相对于其他消息的优先权(priority)、指出该消息可能需要的持久性存储(delivery-mode)等。 - Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序。 - Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。4种类型:direct(默认)、fanout、topic、headers。
direct :点对点
fanout:全部发送、速度最快
topic:模糊匹配,选择性发送给队列 - Queue
消息队列,用来保存消息直到发送给消费者,是消息的容器,也是消息的终点,一个消息可以投入一个或多个队列。 - Binding
绑定,用于消息队列和交换器之间的关联。 - Connection
网络连接,如TCP连接。 - Channel
信道,多路复用连接中的一条独立的双向数据流通道,一个连接存在多个信道。 - Consumer
消息的消费者,表示一个消息队列中取得消息的客户端应用程序。 - Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。 - Broker
表示消息队列服务器实体。
(3)运行机制
- 生产者要发送消息,先把消息发送给broker,即消息服务器;
- 服务器把消息传给交换器,交换器和消息队列绑定;
- 交换器根据消息携带的路由件传给对应消息队列;
- 消费者可以连接队列取到消息。
(4)整合使用
docker中国安装镜像
安装成功可以浏览器查看
- 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
- 配置
spring:
rabbitmq:
host: 118.24.44.169
username: guest
password: guest
自动配置RabbitAutoConfigurationFactor;
RabbitProperties封装RabbitMQ配置;
RabbitTemplate给RabbitMQ发送和接收消息;
AmqpAdmin:RabbitMQ系统管理组件功能;
- 测试
可以使用RabbitTemplate对象发送和接收消息
发送消息与接收消息
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void send(){ //发送
Map<String,Object> map = new HashMap<>();
map.put("msg","这是一个消息");
map.put("date", Arrays.asList("hello",123,true));
//对象被序列化之后发送出去;
// 交换器、路由标识、消息内容
rabbitTemplate.convertAndSend("exchange","routingKey",map);
}
public void receive(){ //接收
Object o = rabbitTemplate.receive("queueName");
System.out.println(o.getClass());
}
消息接收之后会从队列之中消失
- 更改序列化
注入一个配置类
@Configuration
public class rabbitConfig(){
@Bean
public MessageConverter messgaeConverter(){
return new Jackson2MessageConverter();
}
}
(5)监听
- 只要消息队列有消息进入,该注解所在方法执行。
@RabbitListener(queues="消息队列名称");//只要消息队列有消息进入,该注解所在方法执行。
- 如果注解@RabbitListener执行,需要在主程序开启
@EnableRabbit //开启基于注解的rabbitMQ模式
(6)AmqpAdmin:系统管理组件
- 管理交换器exchange、消息队列queue、绑定规则bingding等;