kafka进程启动后又挂掉_Kafka的三种客户端线程模型和一个小惊喜

Kafka 作为一个流式数据平台,对开发者提供了三种客户端:生产者 / 消费者、连接器、流处理。本文着重分析这三种客户端的线程模型。看到最后的通常都有惊喜。消费者的线程模型

0.8 版本以前的消费者客户端会创建一个基于 ZK 的消费者连接器,一个消费者客户端是一个 Java 进程,消费者可以订阅多个主题,每个主题也可以多个线程。为了让消息在多个节点被分布式地消费,提高消息处理的吞吐量,Kafka 允许多个消费者订阅同一个主题,这些消费者需要满足“一个分区只能被一个消费者中的一个线程处理”的限制条件。通常,我们会将同一份相同业务处理逻辑的应用程序部署在不同机器上,并且指定一个消费组编号。当不同机器上的消费者进程启动后,所有这些消费者进程就组成了一个逻辑意义上的消费组。

消费组中的消费者数量是动态变化的,当有新消费者加入消费组,或者旧消费者离开消费组,都会触发基于 ZK 的消费组“再平衡”操作。当“再平衡”操作发生时,每个消费者都会在客户端执行分区分配算法,然后从全局的分配结果中获取属于自己的分区。它的缺点是消费者会和 ZK 产生频繁的交互,造成 ZK 集群的压力过大,并且容易产生羊群效应和脑裂等问题。

在 0.8 版本以后,Kafka 重新设计了客户端,并且引入了“协调者”和“消费组管理协议”。新的消费者将“消费组管理协议”和“分区分配策略”进行了分离。协调者负责消费组的管理,而分区分配则会在消费组的一个主消费者中完成。采用这种方式,每个消费者都需要发送下面两种请求给协调者。

  • 加入组请求:协调者收集消费组的所有消费者,并选举一个主消费者执行分区分配工作。
  • 同步组请求:主消费者完成分区分配,由协调者将分区的分配结果传播给每个消费者。

新版本的消费者客户端引入了一个客户端协调者的抽象类,它的实现除了消费者的协调者,还有一个连接器的实现。

连接器的线程模型

Kafka 连接器的出现标准化了 Kafka 与各种外部存储系统的数据同步。用户开发和使用连接器就变得非常简单,只需要在配置文件中定义连接器,就可以将外部系统的数据导入 Kafka 或将 Kafka 数据导出到外部系统。如图 1 所示,中间部分都是 Kafka 连接器的内部组件,包括源连接器(Source Connector)和目标连接器(Sink Connector)。

1c61b363b9814bee4d83f1711cb34221.png

图 1 Kafka 连接器的源连接器与目标连接器

Kafka 连接器的单机模式会在一个进程内启动一个 Worker 以及所有的连接器和任务。分布式模式的每个进程都有一个 Worker,而连接器和任务则分别运行在各个节点上。图 2 列举了连接器和任务在不同 Worker 上的四种分布方式:

  1. 一个 Worker,一个源任务、一个目标任务
  2. 一个 Worker,两个源任务、两个目标任务
  3. 两个 Worker,两个源任务、两个目标任务
  4. 三个 Worker,两个源任务、两个目标任务

2d8de954db8b97b2935434bd59bbbed0.png

图 2 分布式模式的 Kafka 连接器集群

分布式模式下,不同 Worker 进程之间的协调工作类似于消费者的协调。消费者通过协调者获取分配的分区,Worker 也会通过协调者获取分配的连接器与任务。如图 3 所示,消费者客户端和 Worker 客户端为了加入到组管理中,分别通过客户端的协调者对象来和服务端的消费组协调(GroupCoordinator)通信。

a87fab5275e684620543ff8f5b50c870.png

图 3 消费者和 Worker 的工作都是通过协调者分配的

流处理的线程模型

Kafka 流处理的工作流程简单来看分成三个步骤:消费者读取输入分区的数据、流式地处理每条数据、生产者将处理结果写入输出分区,这里面步骤 1 也充分利用了“消费组管理协议”。Kafka 流处理的输入数据源基于具有分布式分区模型的 Kafka 主题,它的线程模型主要由下面三个类组成:

  • 流实例(KafkaStreams):通常一个节点(一台机器)只运行一个流实例。
  • 流线程(StreamThread):一个流实例可以配置多个流线程。
  • 流任务(StreamTask):一个流线程可以运行多个流任务,根据输入主题的分区数确定任务数。

如图 4 所示,输入主题有六个分区,Kafka 流处理总共就会产生六个流任务。流实例可以动态扩展,流线程的个数也可以动态配置。图中一共有三个流线程,则每个流线程会有两个流任务,每个流任务都对应输入主题的一个分区。

1af1b8ab61a066cf1e457ba6477c3c1f.png

图 4 Kafka 流处理的线程模型

Kafka 的流处理框架使用并行的线程模型处理输入主题的数据集,这种设计思路和 Kafka 的消费者线程模型非常类似。消费者分配到订阅主题的不同分区,流处理框架的流任务也分配到输入主题的不同分区。如图 5 所示,输入主题 1 的分区 P1 和输入主题 2 的分区 P1 分配给流线程 1 的流任务,输入主题 1 的分区 P2 和输入主题 2 的分区 P2 分配给流线程 2 的流任务。流处理相比消费者,还会将拓扑的计算结果写到输出主题。

8570481a62fb2a5a79b2a47ef44f2c4a.png

图 5 消费者模型与流处理的线程模型

消费者和流处理的故障容错机制也是类似的。如图 6 所示,假设消费者 2 进程挂掉,它所持有的分区会被分配给同一个消费组中的消费者 1,这样消费者 1 会分配到订阅主题的所有分区。对于流处理而言,如果流线程 2 挂掉了,流线程 2 中的流任务会分配给流线程 1。即流线程 1 会运行两个流任务,每个流任务分配的分区仍然保持不变。

42e6c5df2b7d42e2fad0ce4d6fe50e6a.png

图 6 消费者与流处理的故障容错机制

小 结

Kafka 客户端抽象出来的的“组管理协议”充分运用在消费者、连接器、流处理三个使用场景中。客户端中的消费者、连接器中的工作者、流处理中的流进程都可以看做“组”的一个成员。当增加或减少组成员时,在这个协议的约束下,每个组成员都可以获取到最新的任务,从而做到无缝的任务迁移。一旦理解了“组管理协议”,对于理解 Kafka 的架构设计是很有帮助的。

欢迎工作一到五年的Java工程师朋友们加入Java架构开发: 855835163

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值