Kafka技术内幕 读书笔记之(五) 协调者——协调者处理请求
消费者客户端使用“消费者的协调者对象”( ConsumerCoordinator )来代表所有和服务端协调者节点有关的请求处理,比如心跳请求、
获取和提交分区的偏移量(自动提交任务)、发送“加入组请求”和“同步组请求”从协调者获取到分区 。 服务端处理客户端请求的人口都是KafkaApis类,
它会针对不同的请求类型分发给不同的方法处理 。
服务端定义发送响应结果的回调方法
不同消费者在不同时刻发送请求给服务端,服务端并不会立即发送响应结果给消费者。 为了保证服务端的高性能,虽然服务端不能立即返
回响应结果给消费者但并不意味着服务端对每个请求的处理都是阻塞的 。 那么既要做到不能阻塞请求的处理,又要做到必须返回响应结果给消费
者,服务端的做法是:在处理每个请求时,首先定义一个“发送响应结果的回调方法”( sendResponseCallback() ),回调方法会传给负责消费组
相关业务逻辑的消费组协调者( GroupCoordinator )。 当协调者认为请求完成时,会调用回调方法发送响应结果给消费者 。
为什么要在处理请求刚开始就定义回调方法,而不是在请求真正完成后直接发送响应结果,这样就不需要回调方法了 。 这是因为服务端发送响
应结果给客户端,会创建一个和请求互相关联的响应结果对象,确保“客户端发送给服务端的请求” 和 “服务端返回给客户端的响应结果 ” 是在同一个
网络通道中完成的 。 “创建响应结果时需要持有请求的引 用” , 如果没有在处理请求的地方定义回调方法 ,而是在请求完成时直接创建响应结果并
发送给客户端 , 就需要把请求对象一路传到请求完成的地方才可以 。
服务端处理“加入组请求”中回调方法的参数是“加入组的结果”,然后封装成“加入组的响应”返回给客户端。处理“同步组请求”中回调方法的参数是
“成员状态”, 即分配的分区,然后封装成“同步组的响应”返回给客户端 。客户端从服务端接收的响应结果和服务端返回给客户端的响应结果必须一样 。
协调者是同一个消费组下所有消费者的协调节点 。 一个消费组有多个消费者 ,而消费组只是一个逻辑概念 。 具体涉及消费组相关的业务逻辑操作时
必须有具体的实现类才能完成 , 协调者就充当了这样的管理员角色。 协调者会通过元数据的方式管理消费’组下的所有消费者 。 协调者可以同时管理多个消费组,
所以元数据有两种:消费组的元数据 、消费者的元数据。 消费组的元数据包括了所有消费者的元数据。
消费者和消费组元数据
消费者加入组过程发送的“加入组请求”和“同步组请求”,都会指定消费组编号( groupid )和消费者成员编号(memberId ),同一个消费组编号只
对应一个“消费组元数据”( GroupMetadata ,下文简称“组元数据”)。 服务端使用“消费者成员元数据”( MemberMetadata ,下文简称“成员元数据”)
表示每个消费者发送的元数据信息,并添加到对应的“组元数据”中 。
1. 消费者成员元数据
“成员元数据”类的构造函数参数,有成员编号 、 消费组编号、协议元数据集 。 会话超时时间是由客户端发送“加入组请求 ”时指定的,latestHeartbeat变量
记录了该消费者最近一次发送心跳的时间 。 另外,“成员元数据”最重要的一个信息是 : 当前这个消费者到底分配到了哪些分区( assignment变量),
因为消费者加入组的最终目的就是从协调者获取到分区 。
“成员元数据”还定义了两个值对象,它们分别对应服务端在处理请求时定义的两个发送响应回调方法 :
- awaitingJoinCallback:加入组回调方法
- awai.ti.ngSyncCallback :同步组回调方法
2. 消费组元数据
一个“组元数据” 管理了所有消费者的 “成员元数据” 。 如果添加“成员元数据” 时都还没有“组元数据” (更新时一定存在“组元数据”),就会先创建 “组元数据” 。
创建“组元数据”是必须的,如果没有“组元数据”, 即使有“成员元数据”,也是没有意义的 。
“组元数据”在消费者需要加入或更新时,除了更新对应消费者的“成员元数据” ,还会记录一些其他数据。 比如,协调者会为消费组选择一个主消费者 ,
来代替它执行分区分配工作 。 另外,每个消费者发送“加入组请求时,都会指定一个会话超时时间。协调者会从消费组的所有消费者中,选择
一个最大的会话超时时间,作为“再平衡操作的超时时间 ” 。
消费组元数据中还有一个很重要的数据 : “消费组的当前状态” 。 因为每个消费者加入消费组都分成“加入组”和“同步组”两个步骤,所以协调者在处理不
同消费者的这两种请求时,都需要改变消费组的状态 。 消费组元数据的状态机有 4 种状态:“稳定状态”( Stable )、“准备再平衡状态”( preparingRebalance )、
“等待同步状态”( AwaitingSync )、“离开状态”( Dead )。 协调者新创建一个消费组元数据,这个消费组元数据的初始状态为“稳定状态” 。
协调者处理请求前的条件检查
协调者在处理“加入组请求”和“同步组请求”之前都需要优先做下面的一些条件检查 。
- 协调者不可用,通常是协调者被关闭了 。
- 消费者客户端传递的消费组编号无效,比如没有设置消费组编号 。
- 消费者连接错了协调者,这个协调者不是消费组的协调者。
- 协调者正在加载,通常是协调者自身在进行迁移 。
- 消费者客户端设置的会话超时时间无效。
- 协调者还没有消费组,但消费者的成员编号却不是“未知编号” 。
- 协调者有消费组,消费者的成员编号不是“未知编号”,但是不在消费组中 。
协调者针对上面几种异常情况都有特定的错误码,并且会立即调用定义好的回调方法,把错误信息及时地返回给消费者客户端。
消费者客户端在响应处理器的回调方法中,针对每种错误码都有不同的处理。 比如,如果是“未知编号”错误码,就会重置客户端的成员编号为“未知编号”,
然后重新发送“加入组请求”;如果是GROUP_COORDINATOR_NOT_AVAILABLE或NOT_COORDINATOR_FOR_GROUP , 消费者就会连接新的协调者节点,
并重新发送“加入组请求” 。
允许消费者加入消费组,有下面两种情况 。
- 消费组为空井且成员编号为“未知编号”,允许加入 。 第一个消费者第一次加入组会执行一次。
- 消费组不为空 ,如果成员编号是“未知编号”,允许加入;如果成员变量不是“未知编号”,必须保证 已经在消费组中才允许加入。
协调者处理消费者发送的“同步组请求”同样需要执行条件检查 。 客户端发送“加入组请求”后才会发送“同步组请求”,服务端处理“同步组请求”也一定在处理
“加入组请求”之后 。协调者在正常处理“加入组请求”时一定会创建消费组,在处理“同步组”请求时必须保证消费组不为空。
消费者发送“加入组请求”和“同步组请求”一定是发送到同一个协调者节点 。 协调者在判断有没有消费组之前,会首先判断它是不是消费组的协调者,
如果不是,直接返回 NOT_COORDINATOR_FOR_GROUP错误码 。协调者处理两种情况的最终目的是 : 返回“加入组响应”和“同步组响应” 给消费者客户端。
其中,“加入组响应”要能够返回所有的消费者成员信息,“同步组响应”要能返回消费者的分配信息 。
协调者调用回调方法发送晌应给客户端
1 . 发送“加入组响应”给消费者
协调者要返回“加入组响应”给消费组下的所有消费者之前,会增加纪元编号 、 选择出一个统一的消费组协议 、 将消费组状态更改为“等待同步” 。
因为是要返回“加入组响应”,而消费者成员元数对象保存了 “发送响应的回调方法”,所以只要用调用方法的方式调用值对象,就可以调用到“发送加入
组响应的回调方法” 。
消费组管理了所有的消费者成员, 协调者发送“加入组响应”时,是一次性一起发送响应结果给每个消费者 。但是协调者处理消费者发送的“加入
组请求”并不是同时进行的,这说明协调者在处理某些消费者的“加入组请求”时,并不会立即返回“加入组响应” 。 实际上,这是通过“延迟操作”
来实现的,“延迟操作”类似于延迟的任务,它和消费组的状态机也有关系 。
2 发送“同步组响应”给消费者
协调者没有同时处理每个消费者的“同步组请求”,但最后同时发送了“同步组响应” 。 说明协调者在处理某些消费者的“同步组请求”时,
并不会立即返回“同步组响应” 。
当协调者收到主消费者的“同步组请求 ” 后 ,它会立即返回“同步组响应”给所有的消费者(包括主消费者和普通消费者)。
协调者发送“ 同步组响应”给消费组每个消费者的方式和发送 “加入组响应” 类似。
3. 协调者保存消费组任务
协调者在返回“同步组响应”给消费者之前,会先把“消费组分配结果”( groupAssignment )以普通消息的形式持久化到内部主题(_consumer_offsets )中
如果协调节点出现问题需要进行故障迁移,新的协调者可以从“内部主题” 中读取持久化的消息,重建“消费组分配结果” 。
一个协调者可以充当多个消费组的协调节点,并使用“消费组缓存”保存它管理的所有“消费组元数据” 。迁移协调者时会读取内部主题的“消费组分配结果”,
重新加载到“消费组缓存”中 。 协调者处理“加入组请求”和“同步组请求”时,根据消费者客户端传递的消费组编号查询“消费组元数据” ,会先从
“消费组缓存”中查询,如果“消费组元数据”已经存在,直接使用现有的数据 。
协调者将“消费组分配结果”保存到内部主题之后 , 才会发送“同步组响应”给每个消费者。
Kafka技术内幕 读书笔记之(五) 协调者——协调者处理请求的更多相关文章
- Kafka技术内幕 读书笔记之(五) 协调者——消费组状态机
协调者保存的消费组元数据中记录了消费组的状态机 , 消费组状态机的转换主要发生在“加入组请求”和“同步组请求”的处理过程中 .协调者处理“离开消费组请求”“迁移消费组请求”“心跳请求” “提交偏移量请 ...
- Kafka技术内幕 读书笔记之(五) 协调者——延迟的加入组操作
协调者处理不同消费者的“加入组请求”,由于不能立即返回“加入组响应”给每个消费者,它会创建一个“延迟操作”,表示协调者会延迟发送“加入组响应”给消费者 . 但协调者不会为每个消费者的 “加入组请求 ...
- Kafka技术内幕 读书笔记之(五) 协调者——消费者加入消费组
消费者客户端轮询的3个步骤:发送拉取请求,客户端轮询,获取拉取结果 . 消费者在发送拉取请求之前,必须首先满足下面的两个条件.- 确保消费者已经连接协调者, 即找到服务端中管理这个消费者的协调者节点 ...
- Kafka技术内幕 读书笔记之(四) 新消费者——消费者提交偏移量
消费组发生再平衡时分区会被分配给新的消费者,为了保证新消费者能够从分区的上一次消费位置继续拉取并处理消息,每个消费者需要将分区的消费进度,定时地同步给消费组对应的协调者节点 .新AP I为客户端提供了 ...
- Kafka技术内幕 读书笔记之(六) 存储层——服务端处理读写请求、分区与副本
如下图中分区到 日 志的虚线表示 : 业务逻辑层的一个分区对应物理存储层的一个日志 . 消息集到数据文件的虚线表示 : 客户端发送的消息集最终会写入日志分段对应的数据文件,存储到Kafka的消息代理节 ...
- Kafka技术内幕 读书笔记之(四) 新消费者——新消费者客户端(二)
消费者拉取消息 消费者创建拉取请求的准备工作,和生产者创建生产请求的准备工作类似,它们都必须和分区的主副本交互.一个生产者写入的分区和消费者分配的分区都可能有多个,同时多个分区的主副本有可能在同一个节 ...
- Kafka技术内幕 读书笔记之(三) 消费者:高级API和低级API——消费者消费消息和提交分区偏移量
消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块( FetchedDataChunk )放入分区信息的队列中 . 而每个队列都对应一个消息流( KafkaStream ),消费者客户 ...
- Kafka技术内幕 读书笔记之(一) Kafka入门
在0.10版本之前, Kafka仅仅作为一个消息系统,主要用来解决应用解耦. 异步消息 . 流量削峰等问题. 在0.10版本之后, Kafka提供了连接器与流处理的能力,它也从分布式的消息系统逐渐成为 ...
- Kafka技术内幕 读书笔记之(六) 存储层——日志的读写
-Kafka是一个分布式的( distributed ).分区的( partitioned ).复制的( replicated )提交日志( commitlog )服务 . “分布式”是所有分布式系统 ...
随机推荐
- The Embarrassed Cryptographer POJ - 2635 同余模+高精度处理 +线性欧拉筛(每n位一起处理)
题意:给出两数乘积K(1e100) 和 一个数L(1e6) 问有没有小于L(不能等于)的素数是K的因数 思路:把数K切割 用1000进制表示 由同余模公式知 k%x=(a*1000%x+b* ...
- 【UOJ347】【WC2018】通道 边分治 虚树 DP
题目大意 给你三棵树,点数都是\(n\).求 \[ \max_{i,j}d_1(i,j)+d_2(i,j)+d_3(i,j) \] 其中\(d_k(i,j)\)是在第\(k\)棵数中\(i,j\)两点 ...
- nginx 重定向 说明
一.nginx 两个操作系统的安装见以前的随笔(已安装请跳过) linux上搭建nginx windows上搭建nginx 二.Nginx重定向——直接到项目,而非nginx欢迎页 默认ngin修改n ...
- android 读取EXcel 文件 读取文件内存卡的权限
android 采用Java的读取xls文件的方式实现. 需要导入第三方Jxl.jar 包. 代码改自 其他博主 : 这只摘录下 读取xls文件的部分代码,当然这个代码在安卓平台需要添加下面的权限 ...
- [WC2011]最大XOR和路径(贪心+线性基)
题目大意:给一张无向图,求一条1-n的路径,是路径边权的异或和最小. 题解 这道题的思路很妙,首先我们可以随便找出一条从1到n的路径来,然后我们可以选一些环. 其实不管这个环和这条路径有怎样的关系,我 ...
- urls 管理
问题阐述:如何管理多个app下的路由分发,使得管理更加清晰? 1. 在app下创建urls.py文件 from django.conf.urls import url from django.urls ...
- A.01.09—模块的输出—PWM低端输出
PWM输出在汽车上的应用也比较多,它有三种不同的实现方式. 第一种由软件实现,即软件设定对一个输出口拉高和拉低的时间,形成时高时低的PWM控制:但这种方式目前用得不多,这是由使用需求和软件本身的特性决 ...
- yii2记录
yii2的gridview使用大全 --- 18个问答 Yii2中多表关联查询(hasOne.hasMany.join.joinwith) Yii2.0 RESTful API 之速率限制(包含res ...
- 通俗易懂的来理解Iaas,Paas,SaaS
首先我们先来了解一下这几个单词的意思和完全的英文 Iaas:Infrastructure as a service 基础设施即服务 Paas:Platform as a service 平台 ...
- LOJ#2722 情报中心
解:有个暴力是枚举两条链然后O(n)判定,可以得到15分. 还可以优化一下,枚举一条链,然后第二条链直接求两端点树上带权距离.可以做到O(m(n + m)),但是我用的树剖,跟上面那一档没啥区别Orz ...