消息中间件的了解和使用

📅 2026/6/24 5:44:08
消息中间件的了解和使用
文章目录1. 概述2. 作用3. 常见技术产品1Apache Kafka2RabbitMQ3Apache RocketMQ4Apache Pulsar5ActiveMQ4. 技术选型5. Apache Kafka6. RabbitMQ1 特点2 消息模式3交换机规则7. Apache RocketMQ8. Apache Pulsar9. ActiveMQ1JMS的介绍2JMS的消息类型3端口10. 死信1概念2产生原因3处理方案4最佳实践5注意事项11. 常见问题1如何确保消息写入成功1. 概述消息中间件是一个用于系统之间 异步通信 的 “快递中转站”。 它不要求发送方和接收方同时在线工作而是让发送方把“包裹”即消息交给中间件中间件再可靠地转交给接收方。2. 作用1应用解耦合发送方和接收方不需要知道对方的存在。一个系统出故障或升级不影响另一个系统。 2异步消息发送方发出消息后不用等待接收方处理完可以立即做自己的事。 3流量削峰当流量瞬间暴增比如双11秒杀消息中间件能把大量请求暂存起来让后端系统按自己的节奏慢慢处理避免被冲垮。3. 常见技术产品1Apache Kafka特点 分布式日志/流处理平台 开发语言Java / Scala 单机吞吐量极高(百万级/秒) 延迟毫秒级 拉取模型基于消费组 支持事务但是较有限2RabbitMQ特点 功能最丰富的消息中间件遵循AMQP协议 开发语言Erlang 单机吞吐量中等(万级/秒) 延迟微秒级(低吞吐下) 推送模型支持多协议 不支持事务3Apache RocketMQ特点 金融级分布式消息中间件 开发语言java 单机吞吐量高(十万级/秒) 延迟毫秒级 拉/推 结合功能丰富 对事务强支持(金融级)4Apache Pulsar特点 云原生分布式消息平台 开发语言java 单机吞吐量极高(百万级/秒) 延迟毫秒级 拉取模型支持4种订阅模式 2.7.0 支持事务5ActiveMQ特点 完全遵循JMS(Java Message Service)规范使用简单且稳定。 开发语言java 单机吞吐量低(千级/秒) 延迟100~200ms 支持点对点模型和发布/订阅 模型 支持JMS本地事务和XA分布式事务保证消息原子性4. 技术选型1Kafka大数据时代的王者 优势Kafka的设计理念就是快。它通过顺序写磁盘、零拷贝和批量压缩等机制实现了惊人的吞吐量是大数据生态如Spark、Flink、Hadoop的事实标准。它非常适合作为数据管道在不同系统之间搬运海量数据。 劣势为了追求极致的性能它在功能上做了减法。例如其事务和延迟消息的支持较弱且原生没有管理界面运维相对复杂。 一句话选型如果你面对的是海量数据如日志、用户行为、需要构建实时数据湖或数据管道Kafka是首选。 2RabbitMQ功能丰富的可靠信使 优势RabbitMQ是功能最丰富的消息中间件。它支持AMQP等多种协议提供了Direct、Topic、Fanout等灵活的路由策略。它的社区非常活跃文档齐全且有易用的管理界面对于业务系统解耦和异步处理非常友好。 劣势由于使用Erlang语言开发二次开发和底层原理排查对Java技术栈的团队有较高门槛。当队列堆积大量消息时性能会明显下降。 一句话选型如果你的业务场景复杂需要多种路由规则、面向微服务或传统业务系统且团队希望开箱即用、易于运维RabbitMQ很合适。 3RocketMQ阿里电商双11的产物 优势RocketMQ诞生于阿里巴巴的超大规模电商场景其设计兼具了Kafka的高性能和类似RabbitMQ的丰富功能。它对事务消息、顺序消息、延迟消息的支持非常出色且稳定性经过了双11的严苛考验。 劣势其客户端生态相对有限主要集中在Java阵营。虽然吞吐量高但在极端情况下如刷盘模式的性能稳定性曾被部分用户指出尚有提升空间。 一句话选型如果你在金融、电商领域对数据一致性、消息顺序有强要求并且技术栈以Java为主RocketMQ是很好的选择。 4Pulsar面向未来的云原生新贵 优势作为后起之秀Pulsar采用了存储和计算分离的架构这使得它在集群扩展、多租户隔离、跨地域复制方面具有天生优势。它支持百万级队列非常适合云环境和SaaS平台。 劣势虽然性能优异但其生态成熟度和社区规模目前仍无法与Kafka相比。架构复杂导致学习曲线较陡运维调试如BookKeeper需要更深入的理解。 一句话选型如果你是云原生架构、有多租户需求或计划进行全球化部署且愿意拥抱新技术可以重点关注Pulsar。 5ActiveMQ 优势完全遵循 JMSJava Message Service规范支持JMS定义的两种经典消息模型点对点模型 和 发布/订阅模型。使用简单稳定成熟标准。 劣势吞吐量较低。不适合大数据量。 一句话选型如果项目是基于Java/J2EE的传统企业环境需要的是开箱即用、文档齐全、稳定可靠的消息服务并且规模可控、对吞吐量要求不极致团队对JMS非常熟悉那么ActiveMQ是一个非常合理且经济的选择。 总结 数据量每天亿级甚至更高 - Kafka 或 Pulsar。 数据量每天千万级以下 - RabbitMQ 完全足够且更省心。 需要严格的消息顺序和强事务保证如订单、支付- RocketMQ。 需要灵活的消息路由如根据不同业务类型分发- RabbitMQ。 只需要数据能快速、可靠地流转到下游 - Kafka。 团队以Java为主希望深度掌控 - RocketMQ原生Java方便二次开发。 希望开箱即用社区活跃文档好找 - RabbitMQ。 有专门的SRE团队追求极致性能和云原生架构 - Kafka 或 Pulsar。 规模可控对吞吐量要求不高希望稳定可靠 -ActiveMQ。5. Apache Kafka6. RabbitMQ1 特点生产者将消息发送给交换机再由交换机根据预定义的规则将消息分发给一个或者多个队列每个队列都可以有一个或者多个消费者最后被消费者消费。2 消息模式1. 发布/订阅模式【Publish/Subscribe】 交换机类型Fanout 路由规则无忽略Routing Key 核心特点广播(将收到的消息分发给所有绑定的队列。每条消息都会被所有订阅的消费者消费)。 2. 路由模式【Routing】 交换机类型Direct 路由规则精确匹配 核心特点单播/组播(一条消息只能进入Routing Key完全匹配的一个队列) 3. 主题模式【Topic】 交换机类型Topic 路由规则模糊匹配(通配符) 核心特点模式匹配根据Routing Key的通配符规则将消息发送给匹配的队列更灵活。 4. 头匹配模式【Headers】 交换机类型Headers 路由规则忽略Routing Key基于一组键值对Key-Value的匹配度并通过 x-match 参数来控制匹配的逻辑。 核心特点根据消息的 Headers 属性进行匹配允许基于多个属性如 formatpdf 且 typereport进行复杂的条件判断。3交换机规则格式为 xxx.xxx.xxx.xxx 每个. 分隔一个单词可以有任意个。 #通配符不考虑级数。 *通配符只能是一级。7. Apache RocketMQ8. Apache Pulsar9. ActiveMQ1JMS的介绍JMS是Java Message Service 的简称是java平台上面向消息中间件的技术规范定义了5种不同的消息正文格式 1TextMessage字符串对象 2MapMessage键值对 3ObjectMessage序列化的java对象 4BytesMessage字节数据流 5StreamMessagejava原始值的数据量2JMS的消息类型jms的消息类型有2种分别是点对点类型(Queue) 和 发布/订阅模式(topic)。 1. 点对点模式【queue】 一个生产者对应一个消费者消息一般不会丢失。 每条数据发送后都能被receive接收receive接收后会通知mq消息已经接收mq会对queue中的消息采取删除或者其他操作。 2. 发布/订阅模式【topic】 一个生产者产生的消息可被多个消费者接收消息容易丢失。 只有正在监听topic地址的receiver才能接收到消息如果没有订阅者监听消息就会丢失。3端口activemq 端口号 基于浏览器访问管理平台8161 基于java程序6161610. 死信1概念当一条消息在队列中无法被正常消费时它会被转移到另一个专门的队列---死信队列这条消息就变成了死信。2产生原因1. 消息被消费者拒绝消费者主动调用basicNack(拒绝一条或多条消息) 或者 basicReject(拒绝一条消息)并且requeuefalse(不重新入队) 【比如消息格式错误无法解析等】 2. 消息过期消息设置了生存时间(Time To Live)超时未被消费。【比如订单设置了30分钟支付过期自动取消】 3. 队列达到最大程度队列满了无法再接收新消息根据策觉最早的消息可能变成死信。【比如队列长度限制为1000条第10001条到来时队首消息被移入死信】 4. 消息被路由到空队列消息的路由键无法到匹配任何队列可能会变成死信。【比如生产者发送时指定了一个不存在的队列名】 5. 消费者处理异常消费代码抛出异常并且配置为重试失败后不重新入队列。【比如调用下游接口一直失败重试3次后放弃并且没有重新回入队列】3处理方案1. 自动重试延迟队列过段时间后重新加入队列供消费者消费。 适用于临时性失败比如网络抖动、数据库锁等。 2. 人工运维处理持久化到数据库或者文件中提供管理界面供人工处理。 适用于未知异常 或者 消息格式错误。 3. 死信分析告警自动修复监控死信队列的深度和产生速率设置告警。 适用于重要业务如 支付、订单等4最佳实践1. 设计阶段每个业务队列都应该配置对应的死信队列 2. 死信原因分析通过x-death 头信息 分析死信产生的根本原因 3. 自动重试针对临时性错误(比如超时、锁竞争等)可以设置延迟重试但是要避免无限循环(设置最大重复次数 4. 人工干预对于格式错误、业务逻辑错误等无法自动修复的死信提供管理界面仍处理。 5. 监控告警监控死信队列的深度当积压超过阈值时立刻告警。 6. 幂等性无论是重试还是人工重新发布消费端都要做幂等处理防止重复消费。5注意事项1. 避免死信循环严禁将死信消息直接、无条件地重新投递回产生它的原队列否则会形成无限循环导致消息积压和系统雪崩。 2. 设置独立死信队列为每个重要的业务队列配置独立的死信队列方便隔离问题和定位。 3. 监控与告警对死信队列的消息数量、增长速度等进行实时监控并设置告警以便在问题扩大前及时发现。 4. 注意性能影响在RabbitMQ中使用死信机制可能会对性能产生负面影响比如内存与CPU开销剧增消息头膨胀与网络带宽浪费、死信循环与队头阻塞等。 5. 注意存储容量死信队列应设置较大的存储容量或消息过期时间避免死信堆积影响新消息进入。11. 常见问题1如何确保消息写入成功1. 写入成功的核心 消息中间件确保写入成功的核心就是生产者确认机制。简单来说生产者发送消息后Broker 会返回一个确认信号如果没收到确认或收到错误生产者就知道消息没写成功需要重试或处理。 2. Kafka : 1acks设置成all 或者 -1生产者 要求 领导者副本在确认消息写入成功前必须等待所有同步副本ISR都成功写入这条消息。 2同步发送异常获取通过异常消息或者返回值信息确定消息成功还是失败。 3异步发送回调确认通过回调消息确认消息成功还是失败。 3. RabbitMQ 1开启发布者确认模式确认消息有没有发送成功 2同步发送异常获取 3异步发送回调确认 4. 兜底处理方案 关键消息使用本地消息表定时补偿 本地创建一个表保存消息的发送成功和失败状态。针对发送失败的情况进行重试或者其他操作如果多次重试后仍是失败那么就人工干预处理。