Gobblin Kafka Source源码分析
来源:互联网 发布:mac的网页开发工具 编辑:程序博客网 时间:2024/05/16 11:30
一、getWorkunits()
该函数是重写的抽象类Source中的getWorkunits(),划分Work Unit过程由此开始。
函数实例化KafkaWrapper用于访问Kafka,获取相关信息。KafkaWrapper是Gobblin实现的一个集成了多种KafkaApi的封装。
for (KafkaTopic topic : topics) { threadPool.submit(new WorkUnitCreator(topic, state, Optional.fromNullable(topicSpecificStateMap.get(topic.getName())), workUnits)); }
Source为每一个Topic建立一个WorkUnitCreator线程用于将Topic的抽取任务,该类继承了Runable,调用getWorkUnitsForTopic()划分为Work Unit。
在WorkUnitCreator过程中会跳过一部分partition(具体原因在后面阅读Work Unit创建函数时分析),通过createEmptyWorkUnitsForSkippedPartitions函数创建一个空的实际不执行的WorkUnit,这是为了在任务完成后,仍然记录该partition的相关信息。
int numOfMultiWorkunits = state.getPropAsInt(ConfigurationKeys.MR_JOB_MAX_MAPPERS_KEY, ConfigurationKeys.DEFAULT_MR_JOB_MAX_MAPPERS); return KafkaWorkUnitPacker.getInstance(this,state).pack(workUnits, numOfMultiWorkunits);
最后,从配置文件中获取最大Map数,将WorkUnit合并成为等同于该数量的MultiWorkunits。
二、getWorkUnitsForTopic()
private ListgetWorkUnitsForTopic(KafkaTopic topic, SourceState state, Optional topicSpecificState) { boolean topicQualified = isTopicQualified(topic); List workUnits = Lists.newArrayList(); for (KafkaPartition partition : topic.getPartitions()) { WorkUnit workUnit = getWorkUnitForTopicPartition(partition, state, topicSpecificState); this.partitionsToBeProcessed.add(partition); if (workUnit != null) { if (!topicQualified) { skipWorkUnit(workUnit); } workUnits.add(workUnit); } } return workUnits; }
在Kafka Source的实现中isTopicQualified直接返回true,继承自KafkaSource的类可以重写该方法对topic进行筛选。如果返回值是false,调用skipWorkUnit函数跳过该topic的WorkUnit。
函数中调用getWorkUnitForTopicPartition()为每一个partition创建WorkUnit。最后将全部的WorkUnit加入Unit列表。
三、getWorkUnitForTopicPartition()
该函数是一个重载函数,有两组传入参数,分别为(KafkaPartition,SourceState, Optional<State>)及(KafkaPartition,Offsets, Optional<State>)。
(一)KafkaPartition, SourceState, Optional<State>
在getWorkUnitsForTopic()调用的是这一组参数。程序主要获取EarliestOffset、LatestOffset、StartOffset流程如下:
1、试图从Kafka集群获取指定分区的Offset信息
try { offsets.setEarliestOffset(this.kafkaWrapper.getEarliestOffset(partition)); offsets.setLatestOffset(this.kafkaWrapper.getLatestOffset(partition)); } catch (KafkaOffsetRetrievalFailureException e) { failedToGetKafkaOffsets = true; }
通过KafkaWrapper调用KafkaAPI获取指定分区的Offset,如果获取失败,则将failedToGetKafkaOffsets标记为true。
2、从Gobblin存储的信息中获取上一次读取位置
long previousOffset = 0; boolean previousOffsetNotFound = false; try { previousOffset = getPreviousOffsetForPartition(partition, state); } catch (PreviousOffsetNotFoundException e) { previousOffsetNotFound = true; }
从上一Job执行完成信息中获取previousOffset,如果获取失败,则将previousOffsetNotFound标记为true。
3、根据Offset获取情况,决定本次是否读取数据及从何位置开始读取
(1)如果failedToGetKafkaOffsets为true
没有从Kafka集群获取到指定partition的Offset信息,本次显然无法读取该partition。区分是否读取到上一次执行信息中的Offset,如果没有,则直接返回null,跳过此Unit,如果有,则调用createEmptyWorkUnit()创建一个空的Unit,以在此次执行保存读取位置信息。
(2)判断topics.move.to.latest.offset
如果为true,调用offsets.startAtLatestOffset()将StartOffset设为LatestOffset。
如果为false,且未能读取到previousOffset,由bootstrap.with.offset决定StartOffset为EarliestOffset还是LatestOffset。
如果为false,且读取到previousOffset,则StartOffset为previousOffset,如果previousOffset超出partition的Offset范围,则根据配置参数选取offset。
(3)调用getWorkUnitForTopicPartition()
以(KafkaPartition, Offsets, Optional<State>)调用getWorkUnitForTopicPartition()函数,创建WorkUnit。
(二)(KafkaPartition,Offsets,Optional<State>)调用
private WorkUnit getWorkUnitForTopicPartition(KafkaPartition partition, Offsets offsets, OptionaltopicSpecificState) { Extract extract = this.createExtract(DEFAULT_TABLE_TYPE, DEFAULT_NAMESPACE_NAME, partition.getTopicName()); WorkUnit workUnit = WorkUnit.create(extract); if (topicSpecificState.isPresent()) { workUnit.addAll(topicSpecificState.get()); } workUnit.setProp(TOPIC_NAME, partition.getTopicName()); workUnit.setProp(ConfigurationKeys.EXTRACT_TABLE_NAME_KEY, partition.getTopicName()); workUnit.setProp(PARTITION_ID, partition.getId()); workUnit.setProp(LEADER_ID, partition.getLeader().getId()); workUnit.setProp(LEADER_HOSTANDPORT, partition.getLeader().getHostAndPort().toString()); workUnit.setProp(ConfigurationKeys.WORK_UNIT_LOW_WATER_MARK_KEY, offsets.getStartOffset()); workUnit.setProp(ConfigurationKeys.WORK_UNIT_HIGH_WATER_MARK_KEY, offsets.getLatestOffset()); return workUnit; }
实例化Extract,并以Extract实例化workUnit。然后将相关参数配置加入workUnit。
四、总结
Kafka Source主要工作就是获取Topic、Partition、Offset,并依据这些信息确定本次读取内容,并划分WorkUnit。
- Gobblin Kafka Source源码分析
- Kafka+Gobblin+HDFS实践
- Gobblin采集kafka数据
- Eclipse导入Gobblin源码
- kafka源码分析
- kafka源码分析
- storm-kafka源码分析
- Kafka源码分析
- kafka源码分析
- kafka源码分析一
- kafka源码分析二
- kafka源码分析三
- kafka源码分析之kafka启动-SocketServer
- Kafka学习 -- Producer源码分析
- Kafka源码分析(1)
- Kafka源码分析(2)
- Kafka源码分析(3)
- Kafka源码分析(4)
- Linux Shell从入门到删除根目录跑路指南
- 职业规划之方法论
- ZZULIOJ 2123
- Activity 初始化性能优化
- 网站seo优化中为什么内容占主导地位
- Gobblin Kafka Source源码分析
- Jquery的Ajax函数应用
- HTML5 资源整理
- Java线程:volatile关键字
- fastboot 单刷modem报错解决办法
- 关于Android6.0/7.0权限,以及7.0调用相机和切图的解决办法
- Android开发基础——UI——基础控件(imageView,imageButton)
- float浮动的消除1
- 双击back退出