我原本打算将这篇文章命名为 “设置卡夫卡消息队列群集”。但是, 与 rabbitmq 不同, 卡夫卡不实现消息队列协议 (例如, 高级消息队列协议 (amqp))。amqp 为统一的消息服务提供高级队列协议。它是应用层协议的开放标准, 专为面向消息的中间件而设计。因此, 尽管卡夫卡的使用模式更像是一个队列, 但它仍然不是严格意义上的消息队列。因此, 我决定为本文提供一个更通用的名称: “卡夫卡分布式消息系统概述”。

卡夫卡介绍

linkedin 是第一家使用 java 和 sca 语言开发卡夫卡的公司。其源代码于2011年开源, 2012年成为 apache 软件基金会的顶级项目。2014年, 卡夫卡的几位创始人成立了一家名为 “康鲁利” 的新公司, 专门研究卡夫卡。

卡夫卡项目的目的是为实时数据处理提供一个统一、高吞吐量、低延迟的系统平台。卡夫卡履行以下三项职能:

  1. 发布和订阅:卡夫卡发布与其他消息系统类似的订阅流数据。
  2. 加工方式:卡夫卡编译流处理应用程序并响应实时事件。
  3. 储存方式:卡夫卡安全地将流数据存储在分布式容错群集中。

留言系统

卡夫卡是一个信息系统。让我们更多地了解消息系统及其解决的问题。以当前流行的微服务体系结构为例。假设 web 端有三个面向终端的 web 服务 (微信官方帐户、移动应用程序和浏览器) web 服务 (http 协议), 即 web1、web2 和 web3, 以及三个内部应用程序服务 app1、app2 和 app3 (远程过程调用,例如, wcf 和 grpc)。如果没有消息系统, 并且采用直接连接模式, 则它们之间的通信模式可能如下所示:

1图 1: 在直接连接模式下通信的系统的结构

采用此模式时存在以下问题:

  1. 紧密耦合的服务增加了挑战。如果修改了应用程序服务两个的外部接口, 则调用该接口的所有组件都需要修改。在上面显示的极端情况下 (所有组件都调用接口, 这在实践中是罕见的), 所有其他 web 和应用程序服务都需要修改。
  2. 修改具有紧密耦合服务的接口是很困难的。如果不受控制的第三方应用程序调用接口, 则需要对接口进行修改。这将使第三方应用程序不可用。修改微信的官方界面将导致数千份应用程序失败。
  3. 启动不同版本的接口是解决此问题的方法。提供了各种访问模式, 如 web/vni界面、web 接口和 app/v2.0/接口。接口在次要版本之间兼容;但是, 它们在明显不同且完全调整的版本之间不兼容。
  4. 虽然上述接口规划方法在一定程度上解决了紧耦合问题, 但这种方法并非完全没有挑战。首先, 如果有更新, 需要修改多个版本; 其次, 大量版本需要维护。
  5. 该方法也给操作带来了困难。增加或减少客户端会变得很复杂。如果现在添加应用程序服务4以提供 web 服务所需的功能, 则必须修改 web 服务1、web 服务2和 web 服务3
  • 性能有限, 扩展变得困难。例如, 必须使用第三方工具 (如 zookeeper 或 consul) 来实现负载平衡。另一种方法是重写代码或添加特定配置。
  • 但是, 在引入消息系统后, 结构如下所示:

    2图 2: 消息系统引入后的系统结构

    在引入消息系统后, 前面提到的所有问题都得到了解决。

    1. 组件、web 服务和应用程序服务不再需要彼此关心彼此的接口定义。相反, 他们只需要关注数据结构 (json 结构)。
    2. 没有必要担心卡夫卡的结构。它成熟、标准高、相对稳定。然而, 用于与卡夫卡沟通的协议需要关注。
    3. 卡夫卡提高了性能。它不仅是为了传输大数据而设计的, 而且以其吞吐量满足了大多数企业的要求。
    4. 卡夫卡通过集群简化了扩展。此外, 它还有一个独特的模式, 即提供负载平衡等共同需求。

    两种消息系统模型

    生产者/消费者模型:

    生成器是在数据管道的一端生成消息的应用程序。使用者是在数据管道的一端使用消息的应用程序。

    下面概述了生成器将消息发送到队列的两种情况:

    1. 如果此时没有使用者连接到队列或使用消息, 则会将消息保存在队列中, 直到其已满或使用者处于联机状态。
    2. 如果此时有多个使用者连接到队列, 则一个使用者只会收到一条消息。因此, 在实践中有多个使用者的情况下, 自然会实现负载平衡。

    订阅者模型:

    发布者: 在数据管道的一端生成事件的应用程序。

    订阅服务器: 在数据管道的一端响应事件的应用程序。

    在 publiser/订阅服务器模型中, 发送到队列的数据是以事件而不是消息的形式出现的。在这种情况下, 数据处理是事件的订阅, 而不是消息的使用。

    如果发布者发布事件后没有订阅者连接到队列, 则该事件将丢失, 即没有应用程序对其做出响应。如果订阅者稍后在线, 他将不会收到该事件。

    如果在发布者同时发布事件后多个订阅者连接到队列, 则该事件将向所有订阅者广播, 并且每个订阅者都会收到相同的事件。因此, 负载平衡不存在。

    流处理应用程序

    批处理应用程序和流处理应用程序之间存在差异。可见边界决定了批处理和流处理之间最显著的差异。如果存在, 则称为批处理。例如, 客户端每小时收集一次数据, 将此数据发送到服务器以进行统计, 然后将统计结果保存在统计数据库中。

    如果边界不存在, 则称为流数据 (流处理)。下面是流处理的一个示例: 日志和订单就像数据流一样, 在大型网站上连续生成。如果每个日志和订单的处理在生成后需要不到几百毫秒或几秒钟, 则该应用程序称为流应用程序

    有时, 流处理变得势在必行。例如, 马云希望在大屏幕上显示11月11日在天猫上的订单和销售情况。如果数据中心在 T+1 模式下工作, 可以在 1 1月 1 2日获得 1 1日的数据, 马云就不会高兴了。

    处理流数据的方法不同于处理批处理数据的方法。卡夫卡提供了一个独特的组件, 卡夫卡流, 以处理流数据。卡夫卡为 hadoop 生态系统中的其他项目提供了不同的元素。例如, spark 还使用 spark 流处理流数据。storm 是第一个专门处理流数据的系统。

    除了数据边界外, 处理时间还可用于区分流处理和批处理。批处理的处理周期通常为数小时或数天, 而流处理的处理周期通常为秒。相应地, 批处理称为脱机数据处理, 而流处理则称为实时数据处理。在分钟单位中, 数据处理称为近线数据处理。但是, 数据处理很少讨论, 通常是脱机处理, 除非处理周期变慢。

    存储

    卡夫卡安全地将数据存储在分布式容错群集中。默认存储期间为一周。此外, 卡夫卡自然支持集群。卡夫卡允许我们方便地添加或减少机器, 并指定数据的份数。这可确保群集提供无中断服务, 即使在群集中的单个服务器发生故障时也是如此。

    卡夫卡主要用于传输我们数据中心项目中的数据。让我首先介绍这个项目的背景, 然后提供卡夫卡解决的问题的理解。

    目前, 前端正在运行10个应用程序, 这可能会随着时间的推移而增加。前端应用程序将数据发送到后端数据中心 (简称数据收集器或收集器的应用程序)。收集器对应于多个应用程序。虽然它在大多数情况下处于空闲状态, 但当许多应用程序同时发送数据时, 收集器无法处理数据。在这种情况下, 需要使用缓冲机制, 以便收集器不会太空闲或太忙。卡夫卡在这种情况下可用作数据的缓冲池。

    在本例中, 我选择了卡夫卡, 而不是选择传统的消息队列组件 (如 rabbitmq)。这是因为卡夫卡天生就是为了应对大量数据并提供更好的性能而开发的。

    卡夫卡除了提供数据缓冲外, 还在数据中心发挥 “平稳升级” 的作用。下面概述了一个快速的图表表示:

    3图 3: 平滑升级

    在前面的用例中, 我们使用. net 开发前端、数据收集和数据清理应用程序。ms sql 存储相同。大数据技术帮助我们在 hdfs 和斯帕克斯上存储大量数据, 帮助我们收集统计数据。

    在引入卡夫卡之后, 没有必要改变以前版本的前端、数据收集或数据清理应用程序。可以访问新版本的收集或清理应用程序, 因为卡夫卡允许我们在任何时间点提取数据。

    新版本通过测试后, 只需停止以前版本的应用程序, 就可以轻松切换到新系统。

    引入消息队列后的挑战

    每一枚硬币都有两面。在介绍卡夫卡之后, 将发生以下变化。

    虽然系统中的应用程序并不相互依存, 但它们在很大程度上依赖于卡夫卡

    1. 在实践中, 实施微服务。小额服务提供权力下放, 因为每个服务都可以独立运作, 而不需要依赖其他服务。确定何时使用这两种模式至关重要。
    2. 消息队列自然是异步的。尽管消息队列提高了性能, 但它增加了代码的复杂性。最初, 通过同步使用 rpc 调用返回的结果很简单。但是, 在采用异步消息队列后, 代码编译和调试变得更加复杂。

    这都是为了第1部分。调整在下一次, 当我们将讨论经纪人, 主题, 分区, 和更多!

    Comments are closed.