RabbitMQ与Kafka:两种不同的消息传递方法

在最后两篇 文章中,我们讨论了工业物联网IIoT,它建立了一种架构来接收来自传感器的数据,并自行焊接传感器。 IIoT架构以及任何与BigData兼容的架构的基石都是数据流处理。 它基于消息传递和排队的概念。 现在,用于消息传递的标准已成为Apache Kafka。 但是,为了了解其优点(并了解其缺点),最好了解整个队列系统的操作基础,它们的操作机制,使用模式和基本功能。



我们找到了一系列优秀的文章,它们比较了Apache Kafka和队列系统中另一个(不可忽视的)巨人(RabbitMQ)的功能。 我们已经翻译了该系列文章,向他们提供了评论并进行了补充。 尽管该系列于2017年12月编写,但消息传递系统(尤其是Apache Kafka)的世界变化如此之快,以至2018年夏天,某些事情已经发生了变化。


来源

RabbitMQ vs卡夫卡


消息传递是许多体系结构的核心部分,该领域的两个支柱是RabbitMQ和Apache Kafka。 迄今为止,Apache Kafka已成为数据处理和分析中几乎一种工业标准,因此在本系列文章中,我们将在RabbitMQ和Kafka在实时基础架构中使用的背景下对其进行更深入的研究。


Apache Kafka现在正在兴起,但是似乎他们开始忘记RabbitMQ。 所有的炒作都集中在Kafka上,这是有明显原因的,但是RabbitMQ仍然是消息传递的理想选择。 Kafka之所以将注意力转向自身的原因之一是其对可扩展性的普遍痴迷,显然,Kafka的可扩展性比RabbitMQ高,但是我们大多数人都不关心RabbitMQ所面临的规模问题。 我们大多数人都不是Google或Facebook。 我们大多数人每天处理的消息量从数十万到数亿,而不是数十亿到万亿(但顺便说一句,有些情况下人们将RabbitMQ扩展到数十亿条每日消息)。


因此,在我们的系列文章中,我们不会讨论需要极高可伸缩性的情况(这是Kafka的特权),而是将重点放在所考虑的每个系统提供的独特优势上。 有趣的是,每个系统都有自己的优势,但同时它们彼此之间却有很大的不同。 当然,我写了很多有关RabbitMQ的文章,但向您保证我不会特别偏爱它。 我喜欢做工精良的产品,RabbitMQ和Kafka都是相当成熟,可靠且可以扩展的消息传递系统。


我们将从顶层开始,然后开始研究这两种技术的各个方面。 本系列文章适用于参与组织消息传递系统的专业人员或想要了解较低级别及其应用程序细节的架构师/工程师。 我们将不会编写代码,而是将重点放在两个系统提供的功能,每个系统提供的消息传递过程模板以及决策开发人员和架构师必须做出的决策上。


RabbitMQ与Kafka:两种不同的消息传递方法


在这一部分中,我们将研究RabbitMQ和Apache Kafka是什么,以及它们的消息传递方法。 两种系统都从不同的角度处理消息传递体系结构,每个角度都有优点和缺点。 在本章中,我们不会得出任何重要的结论;相反,我们建议将该文章作为初学者的技术手册,以便我们可以更深入地学习该系列的下一篇文章。


Rabbitmq


RabbitMQ是一个分布式消息队列管理系统。 分布式的,因为它通常作为节点的群集工作,队列在节点之间分布,并且可以选择复制队列,以提高抗错误能力和高可用性。 通常,它实现AMQP 0.9.1并通过其他模块提供其他协议,例如STOMP,MQTT和HTTP。


RabbitMQ使用经典和创新的消息传递方法。 在某种程度上讲,它是经典的,因为它专注于消息队列,并且具有创新性-可以灵活路由。 此路由功能是其独特的优势。 创建一个快速,可伸缩且可靠的分布式消息传递系统本身就是一项成就,但是消息传递路由功能使其在许多消息传递技术中真正出类拔萃。


交换和排队


超级简化的审查:


  • 发布者(发布者)向交易所发送消息
  • Exchange'i将消息发送到队列中并发送给其他交易所
  • RabbitMQ在收到消息后将确认发送给发布者
  • 接收者(消费者)维持与RabbitMQ的持久TCP连接,并宣布接收到哪些队列
  • RabbitMQ将消息推送给收件人
  • 收件人发送成功/错误确认
  • 成功接收后,将从队列中删除消息。

此列表包含开发人员和管理员必须采取的大量决策,以获取他们所需的交付保证,性能特征等,我们将在后面讨论每个决策。


让我们看一个与一个发布者,交换者,队列和接收者一起工作的例子:



1.一位出版商和一位收件人


如果您有多个相同的发布者,该怎么办
消息? 如果我们有几个收件人,每个收件人都想接收所有邮件怎么办?



2.几个出版商,几个独立的收件人


如您所见,发布者将消息发送到同一交换器,该交换器在三个队列中发送每个消息,每个队列有一个收件人。 对于RabbitMQ,队列允许不同的收件人接收所有消息。 与下图比较:



3.多个发布者,一个队列中有多个竞争接收者


在图3中,我们看到三个使用相同队列的收件人。 这些是竞争的收件人,也就是说,它们正在竞争从队列中接收消息。 因此,可以预期平均每个接收者将接收队列中三分之一的消息。 我们使用竞争的接收者来扩展我们的消息处理系统,而使用RabbitMQ做到这一点非常简单:根据请求添加或删除接收者。 无论您有多少竞争的收件人,RabbitMQ都只会将邮件传递给一个收件人。


我们可以把米饭结合起来。 2和3接收多组竞争的收件人,其中每组接收每封邮件。



4.几个发布者,几个与竞争接收者排队


交换器和队列之间的箭头称为绑定,我们将更详细地讨论它们。


质保


RabbitMQ保证“一次性交付”和“至少一次交付”,但不保证“完全一次交付”。


译者注:在Kafka版本0.11之前,不提供一次精确的传递消息传递;当前,Kafka中具有类似的功能。


消息按到达队列的顺序传递(毕竟,这是队列的定义)。 当您有竞争的收件人时,这不能保证邮件处理的完成顺序匹配相同的顺序。 这不是RabbitMQ错误,而是并行处理有序消息集的基本事实。 如您将在下一章有关模板和拓扑的内容中看到的,可以使用Consistent Hashing Exchange解决此问题。


推送和预取收件人


RabbitMQ将消息推送给收件人(也有一个API从RabbitMQ中提取消息,但是此功能目前已被弃用)。 如果邮件到达队列的速度比收件人处理邮件的速度更快,这可能会使收件人不堪重负。 为避免这种情况,每个接收者都可以设置预取限制(也称为QoS限制)。 实际上,QoS限制是对收件人累积的尚未确认的消息数的限制。 当接收器开始滞后时,它就像保险丝一样。


为什么确定队列中的消息是推送(推)而不是卸载(拉)的? 首先,因为延迟时间更少。 其次,理想情况下,当我们有来自同一队列的竞争收件人时,我们希望在它们之间平均分配负载。 如果每个收件人都请求/下载消息,则根据他们请求的数量,工作分配可能会变得相当不均匀。 消息的分布越不均匀,在处理期间消息顺序的延迟和损失就越大。 这些因素将RabbitMQ体系结构定向为一次一次消息推送机制。 这是扩展RabbitMQ的局限性之一。 可以将确认分组的事实减轻了限制。


路由选择


交换基本上是用于队列和/或其他交换的消息路由器。 为了将消息从交换移动到队列或另一个交换,绑定是必需的。 不同的交易所需要不同的绑定。 交换和关联绑定有四种类型:


  • 扇出 定向到所有绑定来交换Pub的Standard子模型的队列和交换器。
  • 直接(直接)。 根据消息附带的路由密钥(由发布者设置)路由消息。 路由密钥是短字符串。 直接交换器将消息发送到/交换队列,该队列具有与路由密钥完全匹配的配对密钥。
  • 主题(主题)。 根据路由密钥路由消息,但允许使用不完全匹配(通配符)。
  • 标头(header)。 RabbitMQ允许您将收件人标头添加到邮件。 标头交换根据这些标头值发送消息。 每个绑定都包括标题值的完全匹配。 您可以使用匹配所需的ANY或ALL值将多个值添加到绑定中。
  • 一致的哈希。 这是交换器,它散列路由密钥或消息头,并且仅在一个队列中发送。 当您需要遵守处理订单保证并且仍然能够扩展收件人时,此功能很有用。


5.主题交流示例


我们还将更详细地考虑路由,但是上面给出了主题交换示例。 在此示例中,发布者使用路由键格式LEVEL(错误级别).AppName发布错误日志。


队列1将接收所有消息,因为它使用带有多个单词的通配符数字。


队列2将接收任何级别的ECommerce.WebUI应用程序日志记录。 它使用通配符*,从而捕获单个主题命名的级别(ERROR.Ecommerce.WebUI,NOTICE.ECommerce.WebUI等)。


队列3将显示来自任何应用程序的所有错误消息。 它使用通配符#覆盖所有应用程序(ERROR.ECommerce.WebUi,ERROR.SomeApp.SomeSublevel等)。


得益于四种消息路由方法,并且具有交换消息以将消息发送到其他交易所的功能,RabbitMQ允许您使用一组功能强大且灵活的消息交换模板。 进一步,我们将讨论死信交换,没有数据的交换和队列(临时交换和队列),RabbitMQ将充分发挥其潜力。


未交付的交换


译者注:当由于某种原因(消费能力不足,网络问题等)而无法从队列中接收消息时,可以将其延迟并分别处理。


我们可以配置队列,以便在以下情况下发送消息以进行交换:


  • 队列超过了指定的消息数。
  • 队列超过了指定的字节数。
  • 邮件传输时间(TTL)已过期。 发布者可以设置消息的生存期,并且队列本身也可以为消息指定TTL。 在这种情况下,将使用两者中较短的TTL。

我们创建一个队列,该队列必须与未传递的消息进行交换,并且这些消息将存储在该队列中,直到采取某些措施为止。


像RabbitMQ的许多功能一样,与无法传递的消息进行交换可以使用最初未提供的模板。 我们可以使用TTL消息并与未传递的消息进行交换,以实现延迟队列和重试队列。


没有数据的交换器和队列


交换和队列可以动态创建,您可以设置自动删除的条件。 这允许使用诸如基于消息的RPC之类的模式。


附加模块


您可能要安装的第一个插件是管理插件,它为HTTP服务器提供了Web界面和REST API。 它非常易于安装,并且具有易于使用的界面。 通过REST API部署脚本也非常简单。


另外:


  • 一致的哈希交换,分片交换等
  • STOMP和MQTT等协议
  • 网钩
  • 其他类型的交换器
  • SMTP整合

关于RabbitMQ,还有很多其他事情可以说,但这是一个很好的示例,可以让您描述RabbitMQ可以做什么。 现在我们来看一下Kafka,它使用完全不同的消息传递方法,同时也具有自己独特的,有趣的功能。


阿帕奇卡夫卡


Kafka是一个分布式的复制提交日志。 Kafka没有队列的概念,考虑到它被用作消息传递系统,乍一看似乎很奇怪。 队列长期以来一直是消息传递系统的同义词。 首先,让我们看一下“分布式,复制的更改提交日志”的含义:


  • 分布式,因为Kafka被部署为节点群集,以实现容错和扩展
  • 已复制,因为消息通常在多个节点(服务器)上复制。
  • 提交日志,因为消息存储在称为主题的分段的仅附加日志中。 这种测井概念是Kafka的主要独特优势。

了解期刊(和主题)和分区是了解Kafka的关键。 那么分区日志与一组队列有何不同? 让我们想象一下它的外观。



6一位生产商,一位细分市场,一位收件人


Kafka并没有像RabbitMQ那样将消​​息放入FIFO队列中并监视该消息的状态,而只是将其添加到日志中,仅此而已。


该消息将保留,无论是否收到了一次或多次。 根据保留策略(也称为窗口时间段)将其删除。 如何从主题中获取信息?


每个收件人都会跟踪它在日志中的位置:有一个指向最后收到的消息的指针,该指针称为偏移地址。 收件人通过客户端库支持此地址,并且根据Kafka的版本,该地址存储在ZooKeeper或Kafka本身中。


日记模型的一个显着特征是,它立即消除了有关邮件传递状态的许多困难,更重要的是,对于收件人,允许他们在以前的相对地址处倒带,返回和接收邮件。 例如,假设您正在部署一个服务,该服务会发出考虑客户下达的订单的发票。 该服务有错误,并且无法在24小时内正确计算所有帐单。 最好使用RabbitMQ,您将需要以某种方式仅在帐户服务上重新发布这些订单。 但是使用Kafka,您只需在24小时前移动此收件人的相对地址即可。


因此,让我们看一下在一个主题中有一个分区和两个收件人的情况下的外观,每个收件人应接收每条消息。



7.一个生产者,一个分区,两个独立的接收者


从该图可以看出,两个独立的接收者接收相同的分区,但是在不同的偏移地址处读取。 计费服务处理消息的时间可能比推送通知服务花费的时间更长。 或计费服务一段时间不可用,并试图在以后赶上。 也许有一个错误,并且偏移地址必须推迟几个小时。


现在假设计费服务需要分为三个部分,因为它不能跟上消息的速度。 使用RabbitMQ,我们只需部署两个从计费队列中获取的计费服务应用程序即可。 但是,Kafka不支持同一分区中的竞争接收者; Kafka并发块是该分区本身。 因此,如果我们需要三个收款人,则至少需要三个分区。 现在我们有了:



8.三个分区和两组三个收件人


因此,可以理解,您至少需要与扩展最多的水平收件人一样多的分区。 让我们来谈谈分区。


分区和收件人组


每个分区是一个单独的文件,在其中保证消息的顺序。 要记住这一点很重要:仅在一个分区中保证消息顺序。 将来,这可能会导致消息队列要求和性能要求之间有些矛盾,因为Kafka的性能也按分区来扩展。 分区不能支持竞争的收件人,因此我们的计费应用程序每个部分只能使用一个部分。


可以通过循环算法或通过哈希函数将消息重定向到段:hash(消息键)%的分区数。 , , , , , , . .


RabbitMQ. . , RabbitMQ , . , .


RabbitMQ . Kafka , .


, , Kafka , RabbitMQ — . RabbitMQ , . Kafka , . , , Kafka , .


, , , ( ). , , . , , , .


RabbitMQ — Consistent Hashing exchange, . Kafka' , Kafka , , , , , -. RabbitMQ , , , .


: , , Id 1000 , Id 1000 . , , . , .


(push) (pull)


RabbitMQ (push) , , . RabbitMQ . , Kafka (pull), . , , Kafka long-polling.


(pull) Kafka - . Kafka , , .


RabbitMQ, , , , . Kafka , .



Kafka /» , , . , .



9.


, , Kafka :


图 10. ,


, :



11.


, , .


, , , , .



12.


. .



:


  • ( , )

, . , , .


Kafka – , , , , , . . , . , , .



— . , 50 . – . , , , .


, , . , , . , . , , , .


. , , .



, RabbitMQ, Kafka, Kafka . RabbitMQ , , ZooKeeper Consul.


RabbitMQ , Kafka. RabbitMQ, , . : .


. , . . , . . . , , - .


, Kafka, . . , , .


, . RabbitMQ , Kafka .


结论


RabbitMQ , . , , . , . , , .


Kafka . , . Kafka , RabbitMQ . , Kafka , RabbitMQ, , .


RabbitMQ.


, , IoT , . : t.me/justiothings

Source: https://habr.com/ru/post/zh-CN416629/


All Articles