
介绍
两个系统或者客户端之间进行消息传送,利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行系统的集成。这个消息传递机制的衍生产物就是 消息中间件
通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信
对于消息中间件而言,作用总结起来就三个:
- 异步化提升性能
- 降低耦合度
- 流量削峰
应用场景
异步通信
有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。
想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们
缓冲
解耦
消息中间件提供了一种基于消息传递的模型,生产者将消息发布到消息队列中,而消费者则通过订阅特定的消息队列来接收消息。
这样,生产者和消费者之间没有直接的依赖关系,它们可以独立地进行开发和演化
扩展性
通过将消息的发布和订阅解耦,系统可以更容易地进行水平扩展,增加消费者来处理更多的消息,而不会对生产者产生影响
容错性
消息中间件通常具备持久化、重试和消息传递保证等特性,能够在面对网络故障或消费者异常情况时保证消息的可靠传递
冗余
有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
许多消息队列所采用的 " 插入 - 获取 - 删除 " 范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
常用消息队列
| 特性 MQ | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 生产者消费者模式 | 支持 | 支持 | 支持 | 支持 |
| 发布订阅模式 | 支持 | 支持 | 支持 | 支持 |
| 请求回应模式 | 支持 | 支持 | 不支持 | 不支持 |
| Api 完备性 | 高 | 高 | 高 | 高 |
| 多语言支持 | 支持 | 支持 | java | 支持 |
| 单机吞吐量 | 万级 | 万级 | 万级 | 十万级 |
| 消息延迟 | 无 | 微秒级 | 毫秒级 | 毫秒级 |
| 可用性 | 高(主从) | 高(主从) | 非常高(分布式) | 非常高(分布式) |
| 消息丢失 | 低 | 低 | 理论上不会丢失 | 理论上不会丢失 |
| 文档的完备性 | 高 | 高 | 高 | 高 |
| 提供快速入门 | 有 | 有 | 有 | 有 |
| 社区活跃度 | 高 | 高 | 有 | 高 |
| 商业支持 | 无 | 无 | 商业云 | 商业云 |
消息中间件中的角色
Queue: 队列存储,常用与点对点消息模型,默认只能由唯一的一个消费者处理。一旦处理消息删除。
Topic: 主题存储,用于订阅/发布消息模型,主题中的消息,会发送给所有的消费者同时处理。只有在消息可以重复处 理的业务场景中可使用,Queue/Topic都是 Destination 的子接口
ConnectionFactory: 连接工厂,客户用来创建连接的对象,例如 ActiveMQ 提供的 ActiveMQConnectionFactory
Connection: JMS Connection 封装了客户与 JMS 提供者之间的一个虚拟的连接。
Destination: 消息的目的地,目的地是客户用来指定它生产的消息的目标和它消费的消息的来源的对象。JMS1.0.2 规范中定义了两种消息传递域:点对点(PTP)消息传递域和发布/订阅消息传递域。
JMS:Java Message Service
点对点 vs 发布/订阅
点对点消息传递域的特点如下:
- 每个消息只能有一个消费者。
- 消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态,它都可以提取消息。
发布/订阅消息传递域的特点如下:
- 每个消息可以有多个消费者。
- 生产者和消费者之间有时间上的相关性。
- 订阅一个主题的消费者只能消费自它订阅之后发布的消息。JMS 规范允许客户创建持久订阅,这在一定程度上放松了时间上的相关性要求 。持久订阅允许消费者消费它在未处于激活状态时发送的消息。 在点对点消息传递域中,目的地被成为队列(queue);在发布/订阅消息传递域中,目的地被成为主题(topic)。
消息可靠性机制
只有在被确认之后,才认为已经被成功地消费了,消息的成功消费通常包含三个阶段 :客户接收消息、客户处理消息和消息被确认。在事务性会话中,当一个事务被提交的时候,确认自动发生。在非事务性会话中,消息何时被确认取决于创建会话时的应答模式(acknowledgement mode)。该参数有以下三个可选值:
Session.AUTO_ACKNOWLEDGE:当客户成功的从 receive 方法返回的时候,或者从 MessageListener.onMessage 方法成功返回的时候,会话自动确认客户收到的消息。Session.CLIENT_ACKNOWLEDGE:客户通过消息的 acknowledge 方法确认消息。需要注意的是,在这种模式中,确认是在会话层上进行:确认一个被消费的消息将自动确认所有已被会话消费的消息。例如,如果一个消息消费者消费了 10 个消息,然后确认第 5 个消息,那么所有 10 个消息都被确认。Session.DUPS_ACKNOWLEDGE:该选择只是会话迟钝的确认消息的提交。如果 JMS Provider 失败,那么可能会导致一些重复的消息。如果是重复的消息,那么 JMS Provider 必须把消息头的 JMSRedelivered 字段设置为 true。
优先级
可以使用消息优先级来指示 JMS Provider 首先提交紧急的消息。优先级分 10 个级别,从 0(最低)到 9(最高)。如果不指定优先级,默认级别是 4。需要注意的是,JMS Provider 并不一定保证按照优先级的顺序提交消息。
消息过期
可以设置消息在一定时间后过期,默认是永不过期。
临时目的地
可以通过会话上的 createTemporaryQueue 方法和 createTemporaryTopic 方法来创建临时目的地。它们的存在时间只限于创建它们的连接所保持的时间。只有创建该临时目的地的连接上的消息消费者才能够从临时目的地中提取消息
参考
消息队列选型到原理:RabbitMQ、Kafka、RocketMQ和ActiveMQ - 掘金