何时该用 RabbitMQ,何时该用 Apache Kafka?

转载自:https://www.sohu.com/a/145359159_747818

人们是如何做决定的呢?日常生活中,每当人们做出复杂或重大决定时,情绪往往起到最终的决定作用。但对于决策专家来说,他们的每一个决定都具有长远影响,因此做决定不能只靠冲动了。通常,高效率的执行者只会在他们凭借自发的专业思维掌握决策所需的所有信息之后,才靠本能、直觉或情绪做出决策。

何时该用 RabbitMQ,何时该用 Apache Kafka?

如今,市场上有几十种消息传递技术、数不清的 ESB 以及将近 100 家 iPaaS 供应商,那么如何选择适合自己的消息传递技术呢?如果您已经选择了合适的技术,并且有所投入,那么是需要全盘更新呢?还是只针对相应工作使用合适的工具呢?您是否已经根据业务需要对手头的工作精心设计过呢?什么工具最适合我呢?一个要采用新消息传递技术的企业,不仅要处理以上问题,还需要做好市场分析和尽职调查。尽管所有这些步骤都很重要,但选择哪一款新技术无疑是一个困难的决定。

这篇文章从目前最新、最热的两款产品:RabbitMQ 和 Apache Kafka 入手,为各位专家提供一些客观公正的权衡方法。这两个产品的起源、设计意图、成功用例、集成功能和开发者体验各不相同。

起源

我们就从起源讲起,因为起源决定了一款软件的整体设计意图,是一个很好的入手点。

RabbitMQ 是一个支持多种消息传递协议的“传统”消息代理。它是首个在功能层次、客户端库、开发工具和文档质量方面达到合理水平的开源消息代理之一。RabbitMQ 在最初开发时,只是为了支持 AMQP(一个具有强大路由功能的开放式连接协议)。尽管 Java 具有 JMS 等消息传递标准,但对于需要分布式消息传递,严重受限于集成场景微服务一体化的非 Java 应用却没什么用。随着 AMQP 的发展,开源消息代理终于实现了跨语言的灵活性。

Apache Kafka 使用 Scala 语言开发,一开始是由 LinkedIn 推出的,用于简化从 Apache Flume 到 Hadoop 的数据摄取。那时,如果使用 Flume 等工具从多个数据源和目标摄取或导出数据,就需要为每一对数据源和目标编写独立的数据管道。Kafka 帮助 LinkedIn 实现了数据管道的标准化,可以从每个系统中一次性获取数据并将数据一次性导入到每个系统,简化了管道和操作。目前,Kafka 已经很好地融入了 Apache Software Foundation 项目生态系统中。另外 Apache Zookeeper 还与 Kafka集成,形成了 Kafka 的分布式分区主干。尽管很多人质疑 Zookeeper 作用不大,但它确实为 Kafka 用户带来了群集优势。

架构与设计

RabbitMQ 是一个通用的消息代理,可支持“点-点”、“请求-应答”和“发布-订阅”等多种通信模式。它使用“智能代理-无声消费者”模式,重注为消费者提供一致的消息传递。它是一款成熟的产品,在正确配置的情况下表现不俗,并在客户端库支持 Java、.NET、node.js、Ruby、PHP 等多种语言。它还有多款插件可以使用,帮助用户将 RabbitMQ扩展到更多用例或集成场景。

何时该用 RabbitMQ,何时该用 Apache Kafka?

简化的 RabbitMQ 整体架构来源

RabbitMQ 中的通信可以按需设置为同步或异步。发布者将消息发送到交换区,消费者从队列中检索消息。利用交换区将生产者与队列解耦,可确保生产者没有硬编码路由决策的负担。此外,RabbitMQ 还提供了一系列分布式部署场景,并要求所有节点都能够解析主机名。RabbitMQ可以针对多节点群集进行设置,实现群集联合,并且不依赖外部服务。

Apache Kafka 擅长处理大量发布-订阅消息和数据流,具有持久、快速和可扩展的特点。Kafka 提供了一种持久的消息存储方案,与数据库有些类似,它在服务器群集中运行,将记录流存储在名为“主题”的分类中。

何时该用 RabbitMQ,何时该用 Apache Kafka?

Apache Kafka 的整体架构

每一条消息都由键、值和时间戳构成。与 RabbitMQ 不同,Kafka 使用无声代理和智能消费者来读取它的缓存区。Kafka 不会跟踪每个消费者读取了哪些消息,也不会只保留未读消息;相反,Kafka 在设定时间段内保留所有消息,由消费者负责通过日志跟踪信息位置。因此,只要消费者的代码编写得当,Kafka 能用很少的开销支持大量消费者并保留大量数据。Kafka 运行的一些外部服务,对于了解、设置和操作是相当重要的。如上图所示,此例中的 Apache Zookeeper 就是所需要的外部服务。

要求和用例

很多开发者是在意识到必须将很多东西连接起来,而其他集成模式不可行时,才开始探索消息传递的。

Apache Kafka 的自身定位是一个分布式信息流平台,但它更广为人知的角色是持久存储库,具备良好的 Hadoop与Spark 支持。其中有很多热门用例,例如网络活动跟踪、指标、日志聚合、流处理、事件溯源和提交日志等等。其中的一个用例是与消息传递相关的,可能会引发一些困惑。

所以,我们来具体说明一下,明确哪些消息传递场景最适合 Kafka,例如:

  1. 从 A 到 B 的流传输,无需复杂的路由,最大吞吐量可达每秒 100k 以上,按分区顺序至少交付一次。

  2. 当您的应用需要访问数据流历史时,按分区顺序至少交付一次。Kafka 是一个持久性消息存储,客户端可以按需“重演”事件流,这与更为传统的消息代理不同;在更为传统的消息代理中,一旦消息完成交付,便会从队列中删除。

  3. 当您拥有能够可靠地跟踪日志偏移的智能客户端时。

  4. 如果您的应用需要一个“无限”队列。

RabbitMQ 是一个通用消息传递解决方案,通常用于帮助 Web 服务器快速响应请求,而非*执行资源密集型程序而导致用户等待结果。它还可以将一条消息分发给多个收件人进行使用,或用来在高负载(每秒 20k 以上)下均衡工作程序之间的负载。当您的需求超出吞吐量极限时,RabbitMQ 可以提供很大帮助:可靠交付功能、路由功能、联合功能、高可用性、安全性、管理工具和其他功能。

下面我们来详细了解一些适用 RabbitMQ 的最佳场景,例如:

  1. 您的应用需要使用 AMQP 0-9-1、STOMP、MQTT、AMQP 1.0 等现有协议的任意组合。

  2. 您需要确保消息交付成熟而且具有明确的一致性保障。

  3. 您的应用需要各种点-点、请求-应答和发布-订阅等通信模式。

  4. 到消费者的复杂路由,将多个服务或应用与重要的路由逻辑集成。

  5. 当与现有的 IT 基础架构集成非常重要时,RabbitMQ 非常合适。

RabbitMQ 也能有效处理上述 Kafka 的若干强大用例,但需要借助额外软件。当应用需要访问流历史时,RabbitMQ 通常与 Apache Cassandra 结合使用;当应用需要一个“无限”队列时,RabbitMQ 可以与 LevelDB 插件配合使用。但单独使用 RabbitMQ 无法实现以上任何一个功能。

开发者体验

RabbitMQ 官方支持 Java、Spring、.NET、PHP、Python、Ruby、Java、Go、Elixir、Objective-C、Swift,并通过社区插件支持很多其他客户端和开发者工具。RabbitMQ 客户端库业已成熟,相关文档也很完善。

Apache Kafka 在这一领域的发展很快。虽然它只提供 Java 客户端,但开源客户端、生态系统项目和适配器 SDK 正在日益增多,让您可以构建自己的系统集成。大部分配置需要通过 .properties 文件或编程方法来完成。

这两个产品的流行对许多其他软件供应商产生了很大影响。所以各大供应商都尽力确保其技术可与 RabbitMQ 和 Kafka 很好地兼容。

安全和操作

安全和操作都是 RabbitMQ 的优势所在。RabbitMQ 管理插件提供了一个 HTTP API与一个基于浏览器的用户界面,用于管理和监控,还为操作人员提供了 CLI 工具。要长期监控数据存储,需要借助 CollectD、Datadog 或 New Relic 等外部工具。RabbitMQ 还提供一系列用于监控、审核和应用故障排除的 API 和工具。除了支持 TLS,RabbitMQ 还提供RBAC,并支持使用 x509 证书进行身份验证。另外,利用插件还可以轻松创建其他身份验证方法。

Apache Kafka 在安全和操作方面面临着严峻挑战。在安全方面,新版 Kafka 0.9 增加了基于 TLS、JAAS 角色的访问控制和 Kerberos、Plain 或 Scram 等的身份验证,使用 CLI 管理安全政策。相比于早期版本中,只允许锁定网络级别的访问不适用于共享多租户,当今版本的 Kafka 可以说是有相当大的改进。

Kafka 使用一个由 shell 脚本、属性文件和特定格式的 JSON 文件组成的管理 CLI。Kafka 代理、生产者和消费者,通过 Yammer/JMX 发布指标,但不保留历史记录,这就好比使用了一个第三方监控系统。借助这些工具,操作人员可以管理分区和主题,查看消费者的偏移位置,以及使用 Apache Zookeeper 为 Kafka 提供的高可用性与容错功能。例如,一个 3 节点 Kafka 群集系统可以 2 次故障后正常运行。因为 Zookeeper 是一个基于定额的系统,仅容许 N/2+1 次故障,所以如果您希望通过 Zookeeper 容许更多故障,则需要另外配备 5 个 Zookeeper 节点。而且,额外的 Zookeeper 节点不能与 Kafka 节点放置在相同的位置,因此构建一个 3 节点 Kafka 系统需要约 8 个服务器。当推算 Kafka 系统的可用性时,无论是在资源消耗还是设计方面,操作人员都必须考虑 ZK 群集的属性。

性能

Kafka 在性能上表现优异:100k/秒的性能通常是人们选择 Apache Kafka 的主要原因。这在一定程度上要求开发人员要严肃认真地编写消费者代码。当然,每秒传送的消息数量很难说明和量化,因为它们受太多因素影响,包括您的环境、硬件、工作负载性质、交付保证方式等。

通过一个 Rabbit 队列每秒推送 20K 消息并不难,实际上就算推送更多消息也不难做到,在保证方面没有很高的要求。队列由一个 Erlang 轻量级线程提供支持,该线程与本地操作系统线程池协同调度,这使它成为一个天然瓶颈,因为一个队列绝不可能完成超出它可以获得的 CPU 周期容许范围的工作。

要增加每秒的消息传输量,通常都需要正确利用环境的平行性,例如可以采取利用智能路由将流量分配到多个队列等措施。当 RabbitMQ 每秒传输的消息量达到 100 万时,那多半都是用了这个方法。但每秒 100 万的消息传输量需要使用很多资源,大约 30 个 RabbitMQ 节点。对于大多数 RabbitMQ 用户而言,使用三到七个 RabbitMQ 节点的群集就可以获得出色的性能。

最后决策

有关市场上其他排名靠前的产品,应该采纳和借鉴一些相关的研究。如果您想深入了解一些热门备选产品,Nicolas Nannoni 的硕士论文值得一读,本文中的一些灵感就来自于这篇论文。论文第 39 页第 4.4 节给出了一个对照表,在两年后仍然相当准确。

论文链接:http://kth.diva-portal.org/smash/get/diva2:813137/FULLTEXT01.pdf

何时该用 RabbitMQ,何时该用 Apache Kafka?

Apache Kafka and RabbitMQ 普通功能比较

最后提醒各位一点,在做市场调研时,应该尽可能听取了利益相关方和业务部门的建议。充分了解业务用例是帮助您在审时度势中做出正确选择的一大因素。最好的做法仔细考虑,慢慢沉淀,到最后再听从直觉。希望本文能帮助取得满意的成果。

何时该用 RabbitMQ,何时该用 Apache Kafka?

Pieter Humphrey 是 Pivotal产品市场营销经理,负责 Java 开发者市场营销。他从 1998 年到加入 Pivotal 之前,在 Oracle长期从事开发者工具、Java EE、SOA、EAI、应用服务器和其他 Java 中间件。他还担任过市场营销人员和销售工程师。