kafka-clients 1.0 高阶API消费消息(未完)
消费消息的请求(按序)
- org/apache/kafka/common/requests/RequestHeader
- org/apache/kafka/common/requests/ApiVersionsRequest
- org/apache/kafka/common/requests/MetadataRequest 批量查询topic的元数据信息
- org/apache/kafka/common/requests/FindCoordinatorRequest 从拿到的topic的元数据中取出leader节点 作为组协调者
- org/apache/kafka/common/requests/JoinGroupRequest
- org/apache/kafka/common/requests/SyncGroupRequest
- org/apache/kafka/common/requests/OffsetFetchRequest
- org/apache/kafka/common/requests/ListOffsetRequest
- org/apache/kafka/common/requests/FetchRequest
- org/apache/kafka/common/requests/HeartbeatRequest
RequestHeader
请求头
| name | type | defaultValue | docString |
| api_key | INT16 | null | 请求接口编号 |
| api_version | INT16 | null | api版本 |
| correlation_id | INT32 | null | 用户提供的一个整数id,用于响应时由响应体带回来 |
| client_id | NULLABLE_STRING | null | 用户提供的client id |
ApiVersionsRequest
查询API版本信息
请求 version:1
仅仅有请求头
响应 version:1
| name | type | defaultValue | docString |
| error_code | INT16 | null | 错误码 |
| api_versions | ARRAY({api_key:INT16,min_version:INT16,max_version:INT16}) | null | broker能支持的api各版本列表。含最低版本,最高版本. |
| throttle_time_ms | INT32 | 0 | 由于配额冲突而阻止请求的持续时间(毫秒)(如果请求未违反任何配额,则为零 |
虽是请求broker端,但是实际还是用的client中的API完成的逻辑:
ApiVersionsResponse.apiVersionsResponse
根据messageFormatVersion 消息格式版本推导出各API版本情况。
API版本 最小的是0 。写的固定的。 最大的是 requestSchemas的length -1 即requestSchemas最大版本。
此处不仅返回每个API的最小版本与最大版本,还返回能支持的API列表。如因版本问题不能支持的API是不会返回的。
能否支持的判断依据是,API依赖的最小消息格式版本小于当前的消息格式版本,那么就支持。
for (ApiKeys apiKey : ApiKeys.values()) {
if (apiKey.minRequiredInterBrokerMagic <= minMagic) {
versionList.add(neApiVersionsResponse.ApiVersion(apiKey));
}
}
MetadataRequest
批量查询topic的元数据信息
请求 version:5
| name | type | defaultValue | docString |
| topics | ARRAY(STRING) | null | 需要查元数据的topic的列表,如果不送则查所有topic的元数据 |
| allow_auto_topic_creation | BOOLEAN | null | 在broker配置了允许自动创建topic时是否自动创建topic |
响应 version:4
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | 由于配额冲突而阻止请求的持续时间(毫秒)(如果请求未违反任何配额,则为零) |
| brokers | ARRAY({node_id:INT32,host:STRING,port:INT32,rack:NULLABLE_STRING}) | null | 所有 活着的 broker的id ip port的信息 |
| cluster_id | NULLABLE_STRING | null | 集群id |
| controller_id | INT32 | null | controller角色的broker的id |
| topic_metadata | ARRAY({error_code:INT16,topic:STRING,is_internal:BOOLEAN,partition_metadata:ARRAY({error_code:INT16,partition:INT32,leader:INT32,replicas:ARRAY(INT32),isr:ARRAY(INT32)})}) | null | topic元数据,分区数、leader broker的id、副本所在broker id列表、isr broker id列表 |
broker端处理
在broker端
- 过滤出授权的topics KafkaApis.handleTopicMetadataRequest
- 查询出授权topics的元数据 KafkaApis.getTopicMetadata
2.1 从缓存中拿,拿到(跟topics的size相同)即返回
2.2 处理没拿到的topic
2.2.1 允许创建topic的,就按默认副本数和默认分区数创建,不能创建的或者创建出错的返回出错信息。创建topic前提是协调者可用。否则COORDINATOR_NOT_AVAILABLE。
2.2.2 返回创建后的metadata
元数据信息有缓存kafka.server.MetadataCache.cache:topic <--> [partitionNo <--> 分区状态封装]
MetadataCache中一系列getxxx方法都是用来读取检索的。
元数据缓存的更新参见 《MetadataCache更新》
FindCoordinatorRequest
查询协调者
请求 version:1
| name | type | defaultValue | docString |
| coordinator_key | STRING | null | 组协调时是组id 事务协调时是事务id |
| coordinator_type | INT8 | null | 协调类型(0 = group, 1 = transaction) |
响应 version:1
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| error_code | INT16 | null | Response error code |
| error_message | NULLABLE_STRING | null | Response error message |
| coordinator | {node_id:INT32,host:STRING,port:INT32} | null | 协调者broker的id ip port |
组协调与事务协调都用这个请求
coordinatorKey 组协调是组id 事务协调时是事务id
分区对应的leader节点就是组协调者
val coordinatorEndpoint = topicMetadata.partitionMetadata.asScala
.find(_.partition == partition)
.map(_.leader) // SimonNote: leader节点作为协调者
这个请求的响应也就是将协调者信息(node_id,host,port)返回去
JoinGroupRequest
加入消费组的请求
请求 version:2
| name | type | defaultValue | docString |
| group_id | STRING | null | 唯一的组标志 |
| session_timeout | INT32 | null | 会话时间,超过这个时间没收到心跳,协调者就认为这个消费者挂了 |
| rebalance_timeout | INT32 | null | 协调者在重新平衡组时等待每个成员重新加入的最长时间 |
| member_id | STRING | null | 由组协调者分配的成员ID,如果是第一次加入,则为空。 |
| protocol_type | STRING | null | 组协调协议实现类的唯一名称 |
| group_protocols | ARRAY({protocol_name:STRING,protocol_metadata:BYTES}) | null | 组成员能支持的组协调协议列表 |
响应 version:2
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| error_code | INT16 | null | Response error code |
| generation_id | INT32 | null | 组的年代? |
| group_protocol | STRING | null | 协调者选中的组协议 |
| leader_id | STRING | null | 组中的leader |
| member_id | STRING | null | 第一次加入的时候组协调者给分的成员id |
| members | ARRAY({member_id:STRING,member_metadata:BYTES}) | null | 组内成员? |
kafka.coordinator.group.GroupCoordinator.handleJoinGroup
一系列的check:
- 协调者是否可用
- 是否是本分区的协调者
- 消费组id是否合法(是否为空)
- 是否协调者正在load中,
GroupMetadataManager会管理当前partition是否在load中 - sessionTimeoutMs是否在组配置的最大最小范围内
向groupManager加入新建的GroupMetadata实例(如果没有的话,有就直接下一步了),GroupMetadata有哪些东西,下面注释写了一部分,但是还包含事务消息用一些offset
/**
* Group contains the following metadata:
*
* Membership metadata:
* 1. Members registered in this group
* 2. Current protocol assigned to the group (e.g. partition assignment strategy for consumers)
* 3. Protocol metadata associated with group members
*
* State metadata:
* 1. group state
* 2. generation id
* 3. leader id
*/
doJoinGroup
一系列的check后,根据group.currentState做相应处理
group.currentState
GroupMetadata.scala中有对group状态定义及action及走向到哪的明确详细描述,非常重要
SyncGroupRequest
请求 version:1
| name | type | defaultValue | docString |
| group_id | STRING | null | group唯一标志 |
| generation_id | INT32 | null | 代的标志? |
| member_id | STRING | null | 第一次加入的时候组协调者给分的成员id |
| group_assignment | ARRAY({member_id:STRING,member_assignment:BYTES}) | null | null |
响应 version:1
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| error_code | INT16 | null | Response error code |
| member_assignment | BYTES | null | null |
OffsetFetchRequest
请求 version:3
| name | type | defaultValue | docString |
| group_id | STRING | null | group id |
| topics | ARRAY({topic:STRING,partitions:ARRAY({partition:INT32})}) | null | topic列表,支持多个topic |
响应 version:3
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| responses | ARRAY({topic:STRING,partition_responses:ARRAY({partition:INT32,offset:INT64,metadata:NULLABLE_STRING,error_code:INT16})}) | null | 列表:topic-[{分区号-offset,元数据信息}] |
| error_code | INT16 | null | Response error code |
ListOffsetRequest
请求 version:2
| name | type | defaultValue | docString |
| replica_id | INT32 | null | follower的broker的id. 正常消费用-1. |
| isolation_level | INT8 | null | 事务消息可见性设置。 使用 READ_UNCOMMITTED (isolation_level = 0)能看到所有消息. 使用 READ_COMMITTED (isolation_level = 1), 非事务消息和已经提交的消息能被看到. 更具体一点, READ_COMMITTED 返回比当前 LSO (last stable offset)小的offset, 并允许返回已经取消的事务 |
| topics | ARRAY({topic:STRING,partitions:ARRAY({partition:INT32,timestamp:INT64})}) | null | 列表:topic,partitions{分区号,时间戳} |
响应 version:2
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| responses | ARRAY({topic:STRING,partition_responses:ARRAY({partition:INT32,error_code:INT16,timestamp:INT64,offset:INT64})}) | null | 列表:topic 分区号 错误码 时间戳 offset |
FetchRequest
请求 version:6
| name | type | defaultValue | docString |
| replica_id | INT32 | null | follower的broker的id. 正常消费用-1 |
| max_wait_time | INT32 | null | 等待响应的最大时间 单位ms. |
| min_bytes | INT32 | null | 最小字节 |
| max_bytes | INT32 | null | 最大字节. 单条消息如果超过这个大小也将返回 |
| isolation_level | INT8 | null | 事务隔离级别 |
| topics | ARRAY({topic:STRING,partitions:ARRAY({partition:INT32,fetch_offset:INT64,log_start_offset:INT64,max_bytes:INT32})}) | null | 列表: topic 分区号 取的offset log开始的 offset?? 最大字节. |
响应 version:6
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| responses | ARRAY({topic:STRING,partition_responses:ARRAY({partition_header:{partition:INT32,error_code:INT16,high_watermark:INT64,last_stable_offset:INT64,log_start_offset:INT64,aborted_transactions:ARRAY({producer_id:INT64,first_offset:INT64})},record_set:RECORDS})}) | null | 列表: topic 分区头: 分区号 高水位值 LSO(上次稳定offset), log开始offset,取消事务:生产者id 第一个offset。 消息记录集 |
HeartbeatRequest
请求 version:1
| name | type | defaultValue | docString |
| group_id | STRING | null | group id |
| generation_id | INT32 | null | group的年代 |
| member_id | STRING | null | 第一次加入的时候组协调者给分的成员id |
响应 version:1
| name | type | defaultValue | docString |
| throttle_time_ms | INT32 | 0 | Duration in milliseconds for which the request was throttled due to quota violation (Zero if the request did not violate any quota) |
| error_code | INT16 | null | 响应码 |
kafka-clients 1.0 高阶API消费消息(未完)的更多相关文章
- vue3 高阶 API 大汇总,强到离谱
高阶函数是什么呢? 高阶函数英文名叫:Higher Order function ,一个函数可以接收一个或多个函数作为输入,或者输出一个函数,至少满足上述条件之一的函数,叫做高阶函数. 前言 本篇内容 ...
- JavaScript之数组高阶API—reduce()
一文搞懂JavaScript数组中最难的数组API--reduce() 前面我们讲了数组的一些基本方法,今天给大家讲一下数组的reduce(),它是数组里面非常重要也是比较难的函数,那么这篇文章就好好 ...
- kafka如果有多个patition,消费消息的时候消息是没有顺序的
创建一个2个分区,3个副本的topic,名字叫first kafka-topics.sh --create --zookeeper datanode1:2181 --partitions 2 --r ...
- [大数据] hadoop高可用(HA)部署(未完)
一.HA部署架构 如上图所示,我们可以将其分为三个部分: 1.NN和DN组成Hadoop业务组件.浅绿色部分. 2.中间深蓝色部分,为Journal Node,其为一个集群,用于提供高可用的共享文件存 ...
- Cloudera Hadoop 5& Hadoop高阶管理及调优课程(CDH5,Hadoop2.0,HA,安全,管理,调优)
1.课程环境 本课程涉及的技术产品及相关版本: 技术 版本 Linux CentOS 6.5 Java 1.7 Hadoop2.0 2.6.0 Hadoop1.0 1.2.1 Zookeeper 3. ...
- Spark Streaming + Kafka整合(Kafka broker版本0.8.2.1+)
这篇博客是基于Spark Streaming整合Kafka-0.8.2.1官方文档. 本文主要讲解了Spark Streaming如何从Kafka接收数据.Spark Streaming从Kafka接 ...
- kafka 基础知识梳理-kafka是一种高吞吐量的分布式发布订阅消息系统
一.kafka 简介 今社会各种应用系统诸如商业.社交.搜索.浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战: 如何收集这些巨大的信息 如何分析它 如何及时做到如上两点 ...
- TensorFlow低阶API(四)—— 图和会话
简介 TensorFlow使用数据流图将计算表示为独立的指令之间的依赖关系.这可生成低级别的编程模型,在该模型中,您首先定义数据流图,然后创建TensorFlow会话,以便在一组本地和远程设备上运行图 ...
- Python之旅Day3 文件操作 函数(递归|匿名|嵌套|高阶)函数式编程 内置方法
知识回顾 常见五大数据类型分类小结:数字.字符串.列表.元组.字典 按存值个数区分:容器类型(列表.字典.元组) 标量原子(数字.字符串) 按是否可变区分:可变(列表.字典) 不可变(数字.字符串.元 ...
随机推荐
- UC 网盘:我又回来了
普通用户不限速下载,免费 10GB 空间,支持离线下载 这个域名非常厉害,某里挑选域名果然是值得称赞的.直接使用手机号即可注册登录,默认赠送 10GB 空间.不过目前好像没看到有电脑客户端,电脑上下载 ...
- 发布一个自己做的图片转Base64的软件,Markdown写文章时能用到
markdownpic 介绍 Markdown编辑时图片生成base64 软件架构 使用了.netcore winform框架 安装教程 直接运行即可 使用说明 拖拽图片文件 双击选择文件 复制粘贴图 ...
- 拿不到offer?阿里HR教你简历应该这样写
首先,要明白公司看重的是你的什么?为什么要聘请你?当然是看重你的能力,聘请你来是要来干活的. 都知道简历是敲门砖,那么这一块砖要怎么才能敲得响,怎么才能敲得开大厂的门. 1 能力萃取!什么是能力萃取? ...
- HttpServletRequest、HttpServletResponse
doGet()/doPost()方法都有两个参数,一个为代表请求的request,另一个代表响应response. request是获取前台传递的内容,response是反馈给前台数据 HttpSer ...
- 如何阅读一本书——分析阅读Pre
如何阅读一本书--分析阅读Pre 前情介绍 作者: 莫提默.艾德勒 查尔斯.范多伦 初版:1940年,一出版就是全美畅销书榜首一年多.钢铁侠Elon.Musk学过. 需要注意的句子: 成功的阅读牵涉到 ...
- Django学习路36_函数参数 反向解析 修改404 页面
在 templates 中创建对应文件名的 html 文件 (.html) 注: 开发者服务器发生变更是因为 python 代码发生变化 如果 html 文件发生变化,服务器不会进行重启 需要自己手动 ...
- 《JavaScript语言入门教程》记录整理:入门和数据类型
目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...
- python基础day7_编码及小数据池
数字概念,字符串----小数据池 数字的范围:-5---256 字符串: 1,不能有特殊字符 2,s*20还是同一个地址,s*21之后就是另外一个地址 i1 = 6 i2 = 6 print(id(i ...
- Python exec 内置语句
描述 exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码.岭组词 https://www.cgewang.com/post/2205 ...
- 字典内置函数&方法
字典内置函数&方法 Python字典包含了以下内置函数:高佣联盟 www.cgewang.com 序号 函数及描述 1 cmp(dict1, dict2)比较两个字典元素. 2 len(dic ...