Apache ActiveMQ 与 Kafka | Baeldung## 1. 概述
Apache ActiveMQ 与 Kafka | Baeldung## 1. 概述
在分布式架构中,应用程序通常需要在彼此之间交换数据。一方面,这可以通过直接通信来实现。另一方面,为了实现高可用性和分区容错性,并使应用程序之间的耦合度降低,消息传递是一个合适的解决方案。
因此,我们可以选择多种产品。Apache 基金会提供了 ActiveMQ 和 Kafka,我们将在本文中对它们进行比较。
2. 一般事实
2.1. ActiveMQ
ActiveMQ 是一种传统的消息代理,其目标是确保应用程序之间以安全和可靠的方式交换数据。 它处理的数据量较小,因此专门用于定义良好的消息格式和事务性消息传递。
我们必须注意到,除了这种“经典”版本外,还有另一个版本:ActiveMQ Artemis。这种下一代代理基于 HornetQ,其代码在 2015 年由 RedHat 提供给 Apache 基金会。在 ActiveMQ 网站上,它说:
一旦 Artemis 达到与“经典”代码库足够的功能一致性,它将成为 ActiveMQ 的下一个主要版本。
因此,在比较中,我们需要考虑这两个版本。我们将通过使用术语 “ActiveMQ” 和 “Artemis” 来区分它们。
2.2. Kafka
与 ActiveMQ 相反,Kafka 是一个旨在处理大量数据的分布式系统。 我们可以使用它进行传统消息传递以及:
- 网站活动跟踪
- 指标
- 日志聚合
- 流处理
- 事件溯源
- 提交日志
随着使用微服务构建的典型云架构的出现,这些需求变得越来越重要。
2.3. JMS 及其在消息传递中的演变
Java 消息服务(JMS)是 Java EE 应用程序内发送和接收消息的通用 API。它是消息系统早期演变的一部分,至今仍是标准。在 Jakarta EE 中,它被采用为 Jakarta Messaging。因此,了解核心概念可能很有帮助:
- 一个 Java 原生的,但与供应商无关的 API
- 需要一个 JCA 资源适配器 来实现供应商特定的通信协议
- 消息目的地模型:
- 队列(P2P)以确保消息顺序和即使在多个消费者的情况下也能一次处理消息
- 主题(PubSub)作为发布-订阅模式的实现,这意味着多个消费者将在他们订阅主题的期间接收消息
- 消息格式:
- _头_作为代理处理的标准元信息(如优先级或过期日期)
- _属性_作为消费者可以用于消息处理的非标准化元信息
- 包含有效载荷的 主体 – JMS 声明了五种类型的消息,但这仅与使用 API 有关,与此比较无关
然而,演变的方向是开放和独立的——独立于消费者和生产者的平台,以及独立于消息代理的供应商。 有协议定义了它们自己的消息目的地模型:
- AMQP – 用于与供应商无关的消息传递的二进制协议——使用 通用节点
- MQTT – 用于嵌入式系统和物联网的轻量级二进制协议——使用 主题
- STOMP – 一种简单的基于文本的协议,允许即使从浏览器进行消息传递——使用 通用目的地
另一个发展是将之前可靠的单个消息传输(“传统消息传递”)添加到通过云架构的传播按照“火与忘记”原则处理大量数据。 我们可以说,ActiveMQ 和 Kafka 之间的比较是这两种方法的典型代表的比较。例如,Kafka 的替代品可能是 NATS。
3. 比较
在这一部分,我们将比较 ActiveMQ 和 Kafka 在架构和开发中最有趣的特性。
3.1. 消息目的地模型、协议和 API
ActiveMQ 完全实现了 JMS 消息目的地模型的 队列 和 主题,并将 AMQP、MQTT 和 STOMP 消息映射到它们。例如,一个 STOMP 消息被映射到一个 JMS BytesMessage 在一个 主题 中。此外,它还支持 OpenWire,这允许跨语言访问 ActiveMQ。
Artemis 定义了自己独立于标准 API 和协议的消息目的地模型,并需要将它们映射到这个模型:
- 消息 发送到一个 地址,该地址被赋予一个唯一的名称、一个 路由类型 和零个或多个 队列。
- 一个 路由类型 决定了消息如何从地址路由到绑定到该地址的队列。定义了两种类型:
- ANYCAST:消息被路由到地址上的单个队列
- MULTICAST:消息被路由到地址上的所有队列
Kafka 只定义了 主题,它们由多个 分区(至少 1 个)和可以放置在不同代理上的 副本 组成。找到主题分区的最佳策略是一个挑战。我们必须注意:
- 一条消息被分发到一个分区。
- 仅在一个分区内确保消息顺序。
- 默认情况下,后续消息会通过轮询方式分发到主题的分区中。
- 如果我们使用消息键,则具有相同键的消息将进入同一个分区。
Kafka 有自己的 API。尽管也有 JMS 的资源适配器,但我们应该意识到这些概念并不完全兼容。AMQP、MQTT 和 STOMP 并不被官方支持,但有 AMQP 和 MQTT 的连接器。
3.2. 消息格式和处理
ActiveMQ 支持 JMS 标准消息格式,包括头、属性和主体(如上所述)。代理必须维护每条消息的传递状态,导致吞吐量较低。由于它受到 JMS 的支持,消费者可以从目的地同步拉取消息,或者消息可以被代理异步推送。
Kafka 没有定义任何消息格式——这完全取决于生产者。每条消息没有传递状态,只有每个消费者和分区的 偏移量。一个 偏移量 是最后一条传递消息的索引。这不仅更快,还允许通过重置偏移量重新发送消息,而不必询问生产者。
3.3. Spring 和 CDI 集成
JMS 是 Java/Jakarta EE 标准,因此完全集成到 Java/Jakarta EE 应用程序中。因此,ActiveMQ 和 Artemis 的连接可以很容易地由应用服务器管理。对于 Artemis,我们甚至可以使用嵌入式代理。对于 Kafka,只有在使用 JMS 的资源适配器或 Eclipse MicroProfile Reactive 时,才提供管理连接。
Spring 还为 JMS 以及 AMQP、MQTT 和 STOMP 提供集成。Kafka 也受到支持。使用 Spring Boot,我们可以使用 ActiveMQ、Artemis 和 Kafka 的嵌入式代理。
4. ActiveMQ/Artemis 和 Kafka 的用例
以下要点为我们提供了何时使用哪种产品的最佳方向。
4.1. ActiveMQ/Artemis 的用例
- 每天只处理少量消息
- 高可靠性和事务性
- 即时数据转换,ETL 作业
4.2. Kafka 的用例
- 处理高负载数据
- 实时数据处理
- 应用程序活动跟踪
- 日志记录和监控
- 不进行数据转换的消息传递(这是可能的,但不容易)
- 不进行传输保证的消息传递(这是可能的,但不容易)
5. 结论
正如我们所见,ActiveMQ/Artemis 和 Kafka 都有它们的目的,因此也有它们的理由。了解它们之间的差异以便为正确的情况选择合适的产品是很重要的。以下表格再次简要解释了这些差异:
| 标准 | ActiveMQ 经典版 | ActiveMQ Artemis | Kafka |
|---|---|---|---|
| 用例 | 传统消息传递(可靠,事务性) | 分布式事件流 | |
| P2P 消息传递 | 队列 | 地址带有路由类型 ANYCAST | – |
| PubSub 消息传递 | 主题 | 地址带有路由类型 MULTICAST | 主题 |
| API / 协议 | JMS, AMQP. MQTT, STOMP, OpenWire | Kafka 客户端,AMQP 和 MQTT 的连接器,JMS 资源适配器 | |
| 拉取 vs. 推送消息 | 推送式 | 拉取式 | |
| 消息传递的责任 | 生产者必须确保消息被传递 | 消费者消费它应该消费的消息 | |
| 事务支持 | JMS, XA | 自定义事务管理器 | |
| 可扩展性 | 代理网络 | 集群 | 高度可扩展(分区和副本) |
| 更多的消费者… | …性能变慢 | …不会变慢 |