世界将我包围 誓死都一齐
壮观得有如 悬崖的婚礼
概述
消息队列,简称MQ(Message Queue), 目的是为了提高系统的异步通信、扩展解耦能力
- 如注册为列子,一般注册成功后会发送一条消息给用户,如果当我们将数据保存成功后,继续执行发送消息的逻辑,这时候系统就是在等待发送逻辑运行,会降低系统的速度;其实注册成功后发送消息不是要立即响应成功的,我们可以注册成功后,将要发送的消息放入消息队列,然后发送消息的逻辑代码根据消息队列信息去执行,便提高了系统的运行速度
- 还应用在订单系统的应用解耦,秒杀系统的流量削峰
两种形式
- 队列(queue):点对点消息通信
- 主题(topic):发布(publish)/订阅(subscribe)消息通信
点对点式:
- 消息发送者发送消息,消息代码将其放入一个队列中,消息接受者从队列获取消息,消息读取后移出队列
- 消息只有唯一的发送者和接受者,但不是只有一个接收者,即A、B、C都接收到了这个消息,可是消息被A所接受了,B、C接收到了但是使用不了
订阅式:
- 发送者发送消息到主题,多个接受者监听订阅这个主题,那么消息在到达的同时收到消息
JMS和AMQP
- JMS(Java Message Service),JAVA消息服务,是一个API;基于JVM消息代理的规范,ActiveMQ是JMS实现的
- AMQP(Advanced Message Queuing Protocol),是一个高级消息队列协议,兼容JMS,RabbitMQ是AMQP的实现
RabbitMQ简介
RabbitMQ从整体上来看是一个典型的生产者消费者模型,主要负责接收、存储和转发消息。
架构图如下:
Product,生产者
- 生产者连接到RabbitMQ Broker,建立一个连接( Connection)开启一个信道(Channel)
- 生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等
- 生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等
- 生产者通过路由键将交换器和队列绑定起来
- 生产者发送消息至RabbitMQ Broker,其中包含路由键、交换器等信息。
- 相应的交换器根据接收到的路由键查找相匹配的队列。
- 如果找到,则将从生产者发送过来的消息存入相应的队列中。
- 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
- 关闭信道,关闭连接。
Exchange,交换器
在RabbitMQ中,生产者并非直接将消息投递到队列中。真实情况是,生产者将消息发送到Exchange(交换器),由交换器根据路由规则将消息路由到一个或多个队列中。如果路由不到,或返回给生产者,或直接丢弃,或做其它处理。
RoutingKey,路由KEY
指定消息的路由规则,需要与交换器类型和绑定键(Binding)联合使用才能最终生效,在绑定的条件下,生产者可以在发送消息给交换器时通过指定RoutingKey来决定消息流向哪个消息队列。
Binding
将交换器和队列关联起来,决定交换器的消息发送到哪个队列上
Queue,队列
- RabbitMQ的内部对象,用于存储消息
- 生产者投递消息到队列,消费者从队列中获取消息并消费
- 多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(轮询)给多个消费者进行消费,而不是每个消费者都收到所有的消息进行消费
RabbitMQ四种类型的交换器
direct交换器,fanout交换器,topic交换器,headers交换器
direct交换器
把消息路由到RoutingKey与BindingKey完全匹配的队列中,是完全匹配、单播的形式
- eg:如果路由键为“java”,则只能转发RoutingKey为“java”的消息到绑定的队列中去,不会转发如“java.spring”
fanout交换器
会把发送到该交换器的消息路由到所有与该交换器绑定的队列中,不会匹配路由Key,转发消息是最快的
topic交换器
通过模式匹配分配消息,将路由键和某个模式进行匹配,识别两个通配符:“#”和“”。#匹配0个或多个单词,匹配一个单词
- eg:发送一条消息,RoutingKey为“java.spring”,这时候会匹配到RoutingKey为“java.#”和“#.spring”的队列
headers交换器
不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers 属性进行匹配。该交换器类型性能较差且不实用,因此一般不会用到
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。