前言

根据源码分析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()

kafka生产者和消费者流程的更多相关文章

  1. [Spark][kafka]kafka 生产者,消费者 互动例子

    [Spark][kafka]kafka 生产者,消费者 互动例子 # pwd/usr/local/kafka_2.11-0.10.0.1/bin 创建topic:# ./kafka-topics.sh ...

  2. kafka生产者和消费者api的简单使用

    kafka生产者和消费者api的简单使用 一.背景 二.需要实现的功能 1.生产者实现功能 1.KafkaProducer线程安全的,可以在多线程中使用. 2.消息发送的key和value的序列化 3 ...

  3. Kafka 生产者和消费者入门代码基础

    这篇博文讲解Kafka 的生产者和消费者实例. 基础版本一 生产者 ProducerFastStart.java package com.xingyun.tutorial_1; import org. ...

  4. kafka-python开发kafka生产者和消费者

    1.安装kafka-python 执行命令 pip install kafka-python kafka-python        1.4.6 2.编写python kafka 生产者消费者代码 # ...

  5. Kafka 生产者、消费者与分区的关系

    背景 最近和海康整数据对接, 需要将海康产生的结构化数据拿过来做二次识别. 基本的流程: 海康大数据 --> kafka server --> 平台 Kafka 的 topic 正常过车 ...

  6. kafka学习(三)kafka生产者,消费者详解

    文章更新时间:2020/06/14 一.生产者 当我们发送消息之前,先问几个问题:每条消息都是很关键且不能容忍丢失么?偶尔重复消息可以么?我们关注的是消息延迟还是写入消息的吞吐量? 举个例子,有一个信 ...

  7. kafka生产者和消费者

    在使用kafka时,有时候为验证应用程序,需要手动读取消息或者手动生成消息.这个时候可以借助kafka-console-consumer.sh和kafka-console-producer.sh 这两 ...

  8. springboot配置kafka生产者和消费者详解

    在原有pom.xml依赖下新添加一下kafka依赖ar包 <!--kafka--> <dependency> <groupId>org.springframewor ...

  9. kafka生产者、消费者java示例

    1. 生产者 import java.util.Properties; import kafka.javaapi.producer.Producer; import kafka.producer.Ke ...

随机推荐

  1. DOM操作的性能问题

    造成DOM操作性能差的原因:1.DOM操作的实现和ECMAscript的实现是两个独立的部分,之间通过接口来完成相应的DOM操作. 2.实时查询文档得到HTML集合,重复执行查询操作.特别是lengt ...

  2. 【Android 7.1.1】 锁屏界面点击“空白处”响应事件

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLa ...

  3. Dell、IBM服务器配置远程管理卡

    author: headsen  chen date: 2018-10-09 14:12:32 1,IBM的服务器: 需要在bios里边进行配置,具体配置如下: , 开机画面过完之后,按F1进入bio ...

  4. C++ XML 序列化器

    http://www.cppblog.com/xlshcn/archive/2007/11/21/cppxmlserializer.html

  5. Linux系统修改编码(转)

    Windows的默认编码为GBK,Linux的默认编码为UTF-8.在Windows下编辑的中文,在Linux下显示为乱码.为了解决此问题,修改Linux的默认编码为GBK.方法如下: 方法1: vi ...

  6. ThinkPHP的增删改查!

    对表的操作: 增加:M('表名')->add($data);  (可以是数组) 删除:M('表名')->delete($data); (不可以是数组,删除多个有另外的方法) 修改:M('表 ...

  7. 基于JDK1.8的String源码学习笔记

    String,可能是学习Java一上来就学习的,经常用,但是却往往只是一知半解,甚至API有时也得现查.所以还是老规矩,倒腾源码. 一.java doc 这次首先关注String的doc,因为其实作为 ...

  8. Java Naming and Directory Interface (JNDI) Java 命名和目录接口

    https://www.oracle.com/technetwork/java/jndi/index.html Lesson: Overview of JNDI (The Java™ Tutorial ...

  9. Bean Life Cycle

    Bean生命周期 Spring Bean Life Cycle https://www.tutorialspoint.com/spring/spring_bean_life_cycle.htm The ...

  10. Kafka Consumer接口

    对于kafka的consumer接口,提供两种版本,   high-level 一种high-level版本,比较简单不用关心offset, 会自动的读zookeeper中该Consumer grou ...