• kafka生产者和消费者流程


    前言

    根据源码分析kafka java客户端的生产者和消费者的流程。

    基于zookeeper的旧消费者

    kafka消费者从消费数据到关闭经历的流程。

    由于3个核心线程

    1. 基于zookeeper的连接器监听该消费者是否触发重平衡,并获取该消费者客户端消费的topic下group对应的partition以及offset。参考` ZookeeperConsumerConnector`
    2. 寻找partition leader线程循环寻找partition的leader,原理是基于zk的watch,并判断哪些partition的leader发生改变,如果有发生改变,那么创建新的线程来消费这些partition,并把检查之前的线程,如果有消费不是最新的leader那么就shutdown,参考`ConsumerFetcherManager`
    3. 数据拉取线程通过消费partition的leader,循环拉取数据

    解放zookeeper的新消费者

    总体思路

    1. 解放了消费者对zookeeper的依赖,现在只需要和broker交互就可以获取所有需要的元数据。因此,和zk相关的线程都被解放了,取而代之的是基于事件触发思想的流程。
    2. 减少了不必要的线程,将所有操作lazy化处理,也就是说整个消费流程是基于事件的。比如之前有专门维护心跳的线程,现在改为将心跳任务加入队列,只有在某些事件达到时才会执行。由于在拉取数据时,频繁去检验分区相关元数据会导致拉取性能下降,因此消费者每次在拉取完一批record后,会自动异步去拉取下一批的数据,并更新最新的元数据到内存,而此时使用者正在处理上一批的record,这样处理就保证了基于事件思路下的元数据更新和拉取数据的性能。

    拉取数据的两种方式

    1. 手动分配topic和partition,也就是assign,分配之后,消费者客户端不会感知到其他事件的触发。
    2. 订阅topic,自动分配到topic的partition,以及该groupid之前消费到的offset,当然也可以自动感知到kafka的rebalance,并获取到相关事件。

    拉取流程

    1. 确保kafka协调者认可了此次消费,并初始化和协调者的连接。认可很多层次的含义,包括kafka集群是否正常,安全认证是否通过之类。
    2. 确保分区被分配,除了手动assgin的topic,partition和offset,自动subscribe需要从kafka协调者获取相关元数据,也是发生重平衡事件的来源。
    3. 确保已经获取拉取的offset,否则为从协调者那重新获取对应groupid的offset,如果获取失败(比如这是一个新的groupid),那么会重置offset,根据配置用最旧或者最新来代替。参考`ConsumerCoordinator`
    4. 拉取数据,通过拉取每个partition的leader,基于NIO思路拉取数据缓存在内存中;参考`Fetcher`。
    5. 提交offset,如果开启自动提交offset的功能,那么消费者会在两个情况同步提交offset,(1)重平衡或者和broker心跳超时,参考流程2;(2)消费者关闭。如果是手动提交的话可以采用异步或者同步两种提交方式

    重平衡触发原因

    1. 消费的topic的partition数量发生了变化
    2. topic被创建或者删除
    3. 有其他消费者客户端使用相同的group来消费或者停止消费同一个topic

    数据拉取线程分为两类

    kafka集群在同步副本数据的过程,也是基于客户端拉取数据,和消费者稍有不同

    1. 基于消费者的数据拉取线程

    这也就是我们常用的消费者,数据拉取后缓存在内存中给客户端获取

    1. 基于副本备份的数据拉取线程

    kafka集群的副本通过此类线程拉取数据,并写到本地日志中

    kafka生产者

    相对消费者,生产者的流程简单很多。

    生产者采用双线程的方式,主线程也就是用户线程,将数据交给kafka的生产者;另外一个是生产者自己的子线程,将数据源源不断的发送到kafka。

    生产流程

    1. 找到数据发送的partition;
    2. 将数据按照topic partition分类,每类采用一个双向队列存储数据;检查队列最后一个批是否正在处理,尝试加入到该批,否则创建一个新的批并加入到队列末尾。如果最后一个批已经满了(容量满了或者数据超过1)或者有新的批被创建了,那么触发生产者将数据发送到kafka
    3. 另外生产者的子线程也会不断的自我循环,判断内存中缓存的数据是否可以被发送到kafka,有5种情况,只要满足其一就把数据发送到broker,full || expired || exhausted || closed || flushInProgress();(1) full参考流程2;(2) expired 距离上一次数据发送的时间超过了一个阈值;(3) exhausted 生产者内部维护了内存队列,记录了当前使用的内存大小,exhausted表示申请的总数>1的情况;(4) closed 生产者被关闭了;(5) 使用者显示的调用了flush()
  • 相关阅读:
    【美团面试题】——图遍历
    ubuntu15.04 + ROS jade
    3P(PS、PR、PDF编辑器Acrobat)中的基基本操作(三)
    谈谈你对组件的看法
    Web开发中跨域的几种解决方案
    JS事件模型
    zepto的clone方法于textarea和select的bug修复
    SASS使用总结
    git用法总结
    去除inline-block元素间间距
  • 原文地址:https://www.cnblogs.com/ulysses-you/p/9621858.html
Copyright © 2020-2023  润新知