文章目录
- 1、举例
- 2、MQ异步通信
- 3、背景
- 4、Rocket MQ 角色概述
- 4.1 主题
- 4.2 队列
- 4.3 消息
- 4.4 生产者
- 4.5 消费者分组
- 4.6 消费者
- 4.7 订阅关系
- 5、消息传输模型
- 5.1 点对点模型
- 5.2 发布订阅模型
1、举例
以坐火车类比MQ:
安检大厅就像是一个系统的门面,接受来自四面八方且目的地不同的人流,并完成基础的安全校验。人来了,不是直接涌上火车,而是根据所乘坐的车次,到不同的候车厅等着,火车则是消费这些人,现实中是把他们拉到对应的地方,这个候车厅,就像MQ,而不同的车次走向不同的候车厅,则是“主题”这个概念的味道。
2、MQ异步通信
同步通信下,每个请求直接从调用方发送到被调用方,且要求被调用方立即返回响应结果给调用方,以便确定本次调用是否成功。
异步通信下,调用方只需将请求转换成异步时间(消息)发送给中间代理,发送成功,即可为该异步链路调用完成。剩下的工作会有中间代理可靠地通知到下游的被调用系统,以确保任务执行完成。这个中间代理,一般就是消息中间件。
3、背景
Rocket MQ是阿里专为万亿级超大规模的消息处理而设计,具有高吞吐、低延迟、海量堆积、顺序收发等特点,项目发展:
- 2012年阿里开发Rocket MQ
- 2015年重大特性发布:事务消息、SQL过滤、轨迹追踪、定时消息
- 2016年在阿里云托管,并捐赠给Apache
- 2017年成为Apache的顶级项目
// apache的官网apache.org前,加上技术,如rocketmq
https://rocketmq.apache.org
4、Rocket MQ 角色概述
消息生产者生产出消息,投递到对应的topic主题下的队列里面(一个topic下,有多个Message Queue),消费者组通过订阅主题,从RocketMQ 服务端中获取消息并消费。
4.1 主题
- 一个主题下有多个队列
- 消息类型必须一致:创建主题时,消息类型为顺序消息,却又发送事务消息到该主题,就会返回类型不匹配的异常
- 每种主题只支持一种消息类型
- 主题的拆分,可以根据业务和消息类型这两方面来考虑
4.2 队列
- 主题是一个逻辑概念,队列才是真正存储消息的
- 所有成功发送到队列的消息,默认做持久化
- 生产者指定某个主题,向主题内发送消息,但实际消息发送到该主题下的某个队列中
- 同一队列间的消息天然存在顺序关系,头部最早,尾部最新
- 消息在队列中的位置和消息之间的顺序通过位点(Offset) 进行标记管理
- 可以从任意位点读取任意数量的消息,以此实现类似聚合读取、回溯读取
4.3 消息
- 默认对消息做持久化
- 消息对象的属性有两类,生产者自己定义的 + Rocket MQ服务端自己生成并填充的
- 生产者自己定义的属性有:所要投递到的主题名称、消息类型、消息负载body、索引Key列表、过滤标签tag、定时时间等
- Rocket MQ服务端自己生成并填充的属性有:实际存储当前消息的队列、消息位点offset、消息ID、消息重试次数
4.4 生产者
- 同一个生产者可以向多个主题发送消息,并不需要创建多个生产者,同一个主题也可以接收多个生产者的消息
- 生产者发送消息可以选择同步或者异步
- 生产者可以选择批量发送消息
- 不要频繁创建和销毁生产者(RocketMQ 的生产者是可以重复利用的底层资源,类似数据库的连接池)
- 失败重试和事务控制见后续
// 正确
Producer p = ProducerBuilder.build();
for (int i =0;i<n;i++){
Message m= MessageBuilder.build();
p.send(m);
}
p.shutdown();
// 错误
for (int i =0;i<n;i++){
Producer p = ProducerBuilder.build();
Message m= MessageBuilder.build();
p.send(m);
p.shutdown();
}
4.5 消费者分组
- 一组消费逻辑一致的消费者
- 通过消费者分组内初始化多个消费者实现消费性能的水平扩展
- Apache RocketMQ 以消费者分组的粒度来管理订阅关系
- Apache RocketMQ 的服务端将消息投递给消费者消费时,支持顺序投递和并发投递,也是在消费者组中定义
- 消费者消费消息失败时的重试策略,包括重试次数、死信队列设置等,也是在消费者分组中定义
4.6 消费者
-
消费者必须关联一个指定的消费者分组,以获取分组内统一定义的行为配置和消费状态
-
消费者类型有:PushConsumer类型、SimpleConsumer类型、PullConsumer类型(仅推荐流处理场景使用)
-
RocketMQ 的消费者是可以重复利用的底层资源,类似数据库的连接池,所以不要频繁创建和销毁消费者
// 正确
Consumer c = ConsumerBuilder.build();
for (int i =0;i<n;i++){
Message m= c.receive();
//process message
}
c.shutdown();
// 错误
for (int i =0;i<n;i++){
Consumer c = ConsumerBuilder.build();
Message m= c.receive();
//process message
c.shutdown();
}
4.7 订阅关系
- 订阅关系是针对消费者分组和主题来说的,不是单独的一个消费者
- 如下,两个消费者分组都订阅了主题A,且两个分组要求的数据不同,一个要带Tag a,一个要带Tag b
- 如下,同一个消费者组,也可以订阅两个不同的主题
5、消息传输模型
5.1 点对点模型
- 消费者和生产者之间,只认同一个队列
- 即使消费者有多个,一条消息也只能被唯一一个消费者实例处理
5.2 发布订阅模型
- 同一个主题内的消息,可以被多个订阅组消费
- 每个订阅组都可以拿到全量消息