转载自本人博客:【转载翻译】消息队列 - ActiveMQ、RabbitMQ、Kafka、ZeroMQ
转载自:The System Design Cheat Sheet: Message Queues - ActiveMQ, RabbitMQ, Kafka, ZeroMQ
本文由 Aleksandr Gavrilenko 发布于2023年12月21日
1. 前言
消息队列是异步服务到服务通信的一种形式。它们对于增强系统的可扩展性、可靠性和可维护性非常重要。
主要功能包括:
- 异步通信:允许系统的不同部分进行通信,而无需立即响应,从而更有效地使用资源。
- 服务解耦:使服务能够独立运行,降低系统的复杂度,增强可维护性和可扩展性。
- 负载均衡:将消息均匀分布在不同的服务或工作线程之间,有助于管理工作负载并提高系统性能。
- 有序保留:某些消息队列可以确保消息按照发送顺序进行处理,这对于特定应用程序至关重要。
- 可扩展性:通过添加更多使用者或资源来处理增加的消息流,从而促进应用程序的轻松扩展。
- 速率限制:控制消息处理的速率,这对于管理资源和防止系统过载非常重要。
- 扇出功能:消息队列通常包含扇出机制,该机制允许将单个消息同时传递给多个使用者或服务。
- 数据持久性:提供将消息存储在磁盘或内存中的能力,直到它们被成功处理,确保在系统故障的情况下数据不会丢失。
- 消息过滤和路由:允许根据特定条件或内容路由或过滤消息,从而实现更有针对性和更高效的处理。
2. 组件
对于消息队列的内容,核心的概念是生产者(Producer)、消费者(Consumer)和消息(Message)。
- 生产者(Producer) 是一个应用程序或服务,负责创建消息并将其发送到消息队列。它不需要知道谁将处理消息或何时处理消息。
- 消费者(Consumer)是从队列中检索和处理消息的应用程序或服务。它作用于生产者发送的数据。
- 消息(Message)是从生产者发送到消费者的数据包。它们的大小和格式可能有所不同,范围从简单的文本字符串到复杂的数据结构(如 JSON 或 XML)。
- 消息代理(Message Broker) 是一个中间件工具,它通过接收来自发送方的消息并将其路由到适当的接收方,从而促进不同应用程序或服务之间的通信。它通常提供消息队列、路由、转换和传递保证等功能。
3. 消息传递模型
3.1 两种通用消息传递模型
总的来说,有两种类型的消息传递:点对点消息传递和发布-订阅消息传递。
3.1.1 点对点(Point-to-Point)
- 生产者发送的消息被放置在队列(Queue)中,并由单个使用者使用。
- 它确保每条消息仅由一个接收者处理一次。
3.1.2 发布-订阅(Publish-Subscribe)
- 消息将发布到特定主题(Topic),而不是队列,不仅给单个使用者使用。
- 多个消费者可以订阅一个主题,并接收广播到该主题的消息。
3.2 额外消息交换模式
但是,某些消息传递协议和支持它们的代理使用额外的交换(Exchange)组件进行路由。在这种情况下,消息将首先发布到代理中的交换模块。Exchange 充当路由代理,使用其路由规则将这些消息转发到相应的队列。
区分了以下交换模式:
3.2.1 直接交换(Direct exchange)
- 消息被路由到其绑定键与消息的路由键匹配的队列。
3.2.2 话题交换(Topic exchange)
- 主题交换将在路由键和绑定中指定的路由模式之间执行通配符匹配,以将消息发布到队列。
3.2.3 扇出交换(Fanout exchange)
- 发送到扇出交换的消息将被复制并转发到绑定到该交换的所有队列。
3.2.4 标头交换(Header exchange)
- 标头交换将使用消息标头属性进行路由。
3.2.5 死亡信件(Dead letter)
- 死亡信件队列收集由于各种原因(如处理错误、消息过期或传递问题)而无法成功处理的消息。
4. 协议
消息代理负责将消息从生产者传递到使用者。它们使用特定的协议来定义消息传递的规则和格式。
此域中最受欢迎的协议为以下几种:
4.1 AMQP
全称 Advanced Message Queuing Protocol(高级消息队列协议)
一种二进制协议,专为面向消息的中间件而设计,具有鲁棒性、安全性和互操作性。适用于复杂而可靠的企业消息传递系统。
- 使用案例:企业应用程序、财务系统和业务流程
- 消息模型:点对点、发布-订阅
- 安全性:TLS/SSL、SASL、PLAIN
- 寻址:使用具有路由功能的基于交换和队列的寻址
- 架构实现:基于代理库
4.2 MQTT
全称 Message Queuing Telemetry Transport,消息队列遥测传输
一种轻量级的发布-订阅网络协议,针对高延迟或不可靠的网络进行了优化,非常适合 IoT 方案。
- 使用案例:物联网设备、家庭自动化、移动消息应用程序
- 消息传递模型:发布-订阅
- 安全:TLS/SSL、SASL、普通
- 寻址:它使用基于主题的寻址,其中消息将发布到主题
- 架构实现:基于代理库
4.3 JMS
全称 Java Message Service,Java 消息服务
基于 Java 的消息传递标准为 Java 应用程序中的点对点和发布-订阅消息传递模式提供了接口。
- 使用案例:企业 Java 应用程序,集成多个基于 Java 的系统
- 消息模型:点对点、发布-订阅
- 安全:依赖于底层 Java EE 安全模型
- 寻址:使用 JNDI 查找队列和主题
- 架构实现:它通常在企业服务总线或应用程序服务器之上实现。
4.4 STOMP
全称 Simple Text Oriented Messaging Protocol,面向简单文本的消息传递协议
一种简单的基于文本的协议,易于实现,适用于不需要优先考虑高级消息传递功能的方案。
- 使用案例:快速开发环境和简单的消息传递应用程序
- 消息模型:点对点、发布-订阅
- 安全:平原;依赖于底层传输协议进行加密
- 寻址:基于帧,带有目标、内容类型等的标题。
- 架构实现:基于代理库
4.5 Kafka
全称 Kafka Protocol,Kafka协议
与 Apache Kafka 相关联,Apache Kafka 是一个能够处理高吞吐量数据流的分布式流式处理平台。
- 使用案例:实时分析、数据管道、流处理应用程序
- 消息传递模型:发布-订阅
- 安全:SSL/TLS、SASL
- 寻址:基于主题,具有可伸缩性分区功能。
- 架构实现:具有代理和协调的分布式系统架构。
4.6 ZMTP
全称 ZeroMQ Message Transport Protocol,ZeroMQ 消息传输协议
ZeroMQ 的底层协议是一个高性能异步消息传递库,用于构建可扩展的分布式应用程序。
- 使用案例:高吞吐量、低延迟应用程序、微服务架构。
- 消息模型:请求-回复、发布-订阅、流水线、独占对等。
- 安全:PLAIN、CurveZMQ 和 ZAP
- 寻址:使用套接字灵活寻址
- 架构实现:基于库,支持无代理设计或各种代理配置
5. 代理库
ActiveMQRabbitMQKafkaZeroMQ编写语言JAVAErlangScalaC++跨平台是的是的是的是的开源是的是的是的是的多种语言是的是的是的是的支持协议AMQP、AUTO、MQTT、OpenWire、REST、RSS 和 Atom、Stomp、WSIF、WS 通知、XMPP、WebSocketAMQP、STOMP、MQTT、HTTP基于 TCP 的二进制文件TCP、UDP、inproc、PGM、IPC、TIPC、NORM、SOCKS5服务质量至少一次 最多一次至少一次 最多一次至少一次,最多一次,恰好一次一次至少一次 最多一次消息模式队列、Pub-Sub队列、Pub-Sub、RPC发布-订阅Request-Reply、Pub-Sub、Push-Pull、Dealer and Router、Pair、Exclusive Pair等持性久磁盘、数据库内存、磁盘磁盘-
5.1 ActiveMQ
Apache ActiveMQ 是由 Apache 设计的开源、多协议、基于 Java 的消息代理。它以其稳健性和灵活性而闻名,支持各种消息传递协议和客户端,使其成为集成不同系统的多功能选择。
架构特点:
- 多协议支持:ActiveMQ支持多种消息传递协议,包括AMQP、MQTT、OpenWire、STOMP、JMS等,对不同客户端需求的适应性强。
- JMS Provider:作为 JMS Provider,ActiveMQ 遵循 JMS API,该 API 允许 Java 应用程序的松耦合、异步通信和可靠性。
- 基于代理的架构:ActiveMQ 使用代理架构,其中中央代理处理消息路由、传递和队列。
- 可插拔持久化和存储:提供消息持久化选项,包括数据库存储(持久化)和文件系统存储,支持高性能和高持久化场景。
- 集群和负载均衡:支持集群和负载均衡,实现高可用性和可扩展性。
- 客户端确认:提供不同的消息确认选项,增强消息可靠性。
使用场景:
- 企业集成:非常适合在企业内集成不同的系统,主要是在使用基于 Java 或多个协议的情况下。
- 异步通信:在必须解耦系统组件的情况下很有用,例如在微服务体系结构中。
- 分布式计算(Distributed Computing):促进分布式系统中的消息通信,保证数据的一致性和可靠性。
- 物联网通信:可用于物联网设置,尤其是在首选 MQTT 的情况下。
优点:
- 协议支持的多功能性:ActiveMQ 的主要优势之一是它支持多种协议,在各种环境中提供灵活性。
- 可靠性和耐久性:提供可靠的消息传递和持久的存储。
- 集群和高可用性:支持集群以实现负载均衡和高可用性。
- JMS 支持:对 JMS API 的全面支持使其成为基于 Java 的系统的有力候选者。
缺点:
- 性能:虽然 ActiveMQ 很强大,但可能无法与一些较新的消息代理的性能匹配,尤其是在吞吐量要求极高的场景中。
- 复杂配置:可能难以配置和管理,尤其是在集群设置中。
- 资源使用:可能需要大量资源,尤其是在重负载下,以获得最佳性能。
- 管理和监控: 虽然它提供了管理工具,但它们可能不如一些较新的经纪人全面和用户友好。
5.2 RabbitMQ
RabbitMQ 是一个开源的消息代理软件,被称为面向消息的中间件。它是用 Erlang 编写的,基于 Open Telecom Platform 框架构建,用于集群和故障转移。RabbitMQ 广泛用于处理异步处理,通过各种消息传递协议(主要是 AMQP(高级消息队列协议))实现分布式系统之间的通信。
架构特点:
- 支持多种消息传递协议:虽然 RabbitMQ 主要以 AMQP 而闻名,但它也通过插件支持 MQTT、STOMP 和其他协议。
- 生产者-消费者模型:它遵循标准的生产者-消费者模式,其中生产者发送消息,消费者接收消息,RabbitMQ 充当代理。
- Exchange-Queue 绑定:RabbitMQ 中的消息被发布到交换,然后根据路由键和模式路由到绑定队列。
- 持久消息传递和瞬态消息传递:支持持久消息(在磁盘上持久保存)和瞬态消息(内存中)消息。
- 集群和高可用性:RabbitMQ 可以集群以实现高可用性和可扩展性,在多个节点之间分配队列。
- 灵活的路由:为不同的路由逻辑提供多种交换类型(如直接、主题、扇出和标头)。
- 可插拔认证和授权:支持可插拔认证模块,包括 LDAP。
使用场景:
- 异步处理:非常适合解耦 Web 应用程序中的繁重处理任务,确保响应式用户界面。
- 服务间通信:在微服务架构中用于服务之间的通信。
- 任务队列:非常适合处理后台任务,如发送电子邮件或处理图像。
- 分布式系统:促进分布式系统中的消息通信,保持一致性和可靠性。
优点:
- 可靠性:RabbitMQ 以其可靠性和确保消息传递的能力而闻名。
- 灵活的路由能力:其路由能力比许多消息代理的路由能力更先进。
- 可扩展性和高可用性:支持可扩展的集群,这对于大规模应用程序至关重要。
- 广泛的协议支持:支持多种消息传递协议的能力提高了适应性。
- 管理界面:带有用户友好的管理界面,可简化监视和管理消息流。
缺点:
- 学习曲线:对于初学者来说,了解 RabbitMQ 的路由和设置可能很复杂。
- 内存使用:它可能占用大量内存,尤其是在重负载下,需要适当的监控和调整。
- Erlang 依赖性:基于 Erlang 构建,它引入了一个额外的技术堆栈,团队可能需要熟悉这些技术堆栈。
- 高负载下的性能:虽然通常性能较高,但在极高负载或复杂的路由方案中,可能需要进行性能调整。
5.3 Kafka
Apache Kafka是由 LinkedIn 开发的开源流处理软件平台,后来捐赠给了 Apache 软件基金会。它旨在处理大量数据并实现实时数据处理。Kafka 是一种分布式、分区和复制的提交日志服务。
架构特点:
- 生产者-消费者模型:Kafka 以生产者-消费者模型运行。生产者向 Kafka 主题发布消息,消费者订阅这些主题以阅读消息。
- 主题和分区:Kafka 中的数据分为多个主题。每个主题都可以拆分为多个分区,从而允许并行数据处理。分区还使 Kafka 能够水平扩展。
- 分布式系统:Kafka 在一台或多台服务器上作为集群运行,Kafka 集群将记录流存储在称为主题的类别中。
- 复制:Kafka 跨多个节点(代理)复制数据,以确保容错性。如果一个节点发生故障,可以从其他节点检索数据。
- Zookeeper 协调:Kafka 使用 ZooKeeper 进行集群管理和协调,保证集群间的一致性。
- 提交日志存储:Kafka 将所有数据存储为一系列记录(或提交日志),提供持久的消息存储。
使用场景:
- 实时数据处理:非常适合实时分析和监控系统,在这些系统中,快速数据处理至关重要。
- 事件溯源:适用于记录应用程序中的事件序列。
- 日志聚合:有效用于收集和处理来自多个服务的日志。
- 流处理:可用于复杂的流处理任务,如聚合数据流或实时过滤。
- 与大数据技术集成:通常与大数据工具一起使用,进行数据处理和分析。
优点:
- 高吞吐量:可以处理大量数据和许多并发事务。
- 可扩展性:易于水平和垂直扩展。
- 持久性和可靠性:提供持久的消息存储。
- 容错性:由于数据复制,容错性高。
- 灵活性:可用于广泛的用例,从消息传递系统到活动跟踪和日志聚合。
缺点:
- 复杂性:设置和管理可能很复杂,尤其是对于大型集群。
- 资源密集型:可能是资源密集型的,需要大量的内存和 CPU。
- 对 ZooKeeper 的依赖性:依赖 ZooKeeper 进行协调,添加额外的组件进行管理。
- 延迟:虽然速度很快,但可能不适合需要极低延迟的用例。
5.4 ZeroMQ
ZeroMQ(ØMQ、0MQ 或 ZMQ)是用于分布式或并发应用程序的高性能异步消息库。它不是一个消息代理,而是一个库,它将套接字通信抽象为面向消息的中间件,从而更容易以可扩展的方式实现复杂的通信模式。ZeroMQ是用C++开发的,可以通过绑定在各种编程语言中使用。
架构特点:
- 基于套接字的通信:ZeroMQ 使用套接字来抽象出低级网络编程的复杂性。这些套接字可用于发布-订阅、请求-回复和扇出等模式。
- 无代理设计:与传统的消息代理不同,ZeroMQ 是无代理的,允许端点之间直接通信,而无需中央消息代理。
- 可扩展的多线程:提供了一种通过基于套接字的通信管理多个线程的方法,从而促进了可扩展的 I/O 绑定操作。
- 异步 I/O:支持非阻塞、异步 I/O 操作,这对于构建响应迅速的高性能应用程序至关重要。
- 与语言无关:为多种编程语言提供绑定,使其可以从不同的技术堆栈进行访问。
使用场景:
- 微服务:非常适合微服务架构中的服务间通信。
- 高性能计算:用于性能至关重要的并行处理系统。
- 分布式系统:适合需要复杂的分布式消息传递模式的场景,而不需要代理的开销。
- 实时通信:在需要低延迟、实时数据交换的系统中有效。
优点:
- 高性能:ZeroMQ专为高吞吐量和低延迟而设计,适用于性能关键型应用。
- 消息传递模式的灵活性:支持多种消息传递模式,为不同的通信场景提供灵活性。
- 降低复杂性:无代理架构简化了部署,降低了系统复杂性。
- 可扩展性:通过对多个连接的有效处理,方便了应用程序的扩展。
- 轻量级:与传统消息传递代理相比,资源密集程度更低。
缺点:
- 没有内置持久性或消息持久性:缺乏内置的消息持久性或持久性支持,必须在外部处理。
- 需要显式管理连接:开发人员需要管理连接,重试和错误处理,这可能会增加应用程序逻辑的复杂性。
- 学习曲线:理解和有效使用ZeroMQ的模式可能需要一个陡峭的学习曲线。
- 缺乏中央代理:虽然这可能是一个优势,但它也意味着需要对消息传递系统进行更集中的管理、监控和控制。
版权归原作者 空名_Noname 所有, 如有侵权,请联系我们删除。