HadoopConsumer——消费kafka中若干topic的消息,追加存储至hdfs的不同文件内

原创 2015年11月18日 21:49:13

在kafka源码提供的hadoopconsumer的基础上进行开发,该程序可消费多个topic的消息,追加至hdfs文件中。

本程序的输入输出文件有:

配置文件:topics.properties,指定要消费的topic列表,broker列表,以及程序被调用的时     间间隔Interval、每次消费的上限limit、以及三个输入输出文件的父目录

Offset.dat:输入文件,存储leader broker以及offset,根目录:input

Message.txt:输出文件,将消费的消费追加写入,根目录:outputfilepath

Output:输出文件夹,mapreduce的输出文件夹,不使用

 

DateGenerator

初始化操作,为每一个topic的每一个partition创建相关的文件夹以及文件,仅调用一次:

1) 创建offset.dat存储topicpartitionleader broker IPPort、以及offset值;

offset初始值为-1,之后保存上一次消费过的offset,下次hadoop-consumer被调用则继 续消费;

2) 为map-reduce的输出创建文件夹,他存储的文件名默认为part-00000

3) 程序实现了直接向hdfs的文件追加消息的功能,所以还需创建进行追加的文件message.txt

增加的功能:

首先依据配置文件获取topic列表,以及broker列表,然后获取每个topic的分区数,为每个分区创建以上的三个文件(文件夹);

创建offset.dat时要先获取该partition此刻的leader,然后写入文件;

 

KafkatoHDFSMain

增加的功能:

使用线程池,依据topic的个数创建线程,一个topic开启一个线程去消费消息;

每个线程内的run函数里面sleep一定时间间隔后,无限次地调用SimpleKafkaETLJobexcute方法,不断地消费消息;

 

SimpleKafkaETLJob

构造函数中需指定topic,然后为该topic每一个分区创建一个hadoopjob,消费消息并存储;

之后就是一个个job在执行;

runningJob.isSuccessful()会判断此job是否执行成功,如果不成功,会输出信息;

KafkaETLJobcreateJobConf()函数中给JobConf增加一项配置:partition_id,原来只有topic

 

KafkaETLRecordReader

通过KafkaETLInputFormat BytesWritable获取offset.dat文件的记录作为输入,消费指定topic、指定partition、指定offset的消息,然后先写入本地文件,之后将文件追加至message.txt

增加的功能:

Next()函数消费消息,通过limit指定消费的数据量;

消费完之后输出消费的总量System.out.println("_readBytes"+_readBytes);

在本地新建文件,将context中得到消息的ArrayList一条一条写入其中,之后将整个文件追加至hdfsmessage.txt文件;

而不是之前的一条一条消息追加;

最后重写offset.dat文件,记录本次消费过的offset值,便于下次继续消费;

 

KafkaETLContext

使用simpleconsumerAPI,获取offset值,实时获取leader broker,一条一条消费消息,并存储至ArrayList中。

增加的功能:

the_last_offset:创建一个变量,记录上一次被调用消费到的offset值;

message_list:消费的消息先存储于此,之后将list中的消息写入本地文件,再批量追加至hdfs

获取此刻该partitionleader broker,使用新的leader创建requestconsumer,开始消费;

_limit = props.getInt("kafka.request.limit", -1);

_offset = _offsetRange[0];

if((_offsetRange[0]+_limit) < _offsetRange[1])

the_last_offset = _offsetRange[0]+_limit;

else

the_last_offset = _offsetRange[1];

如果消息量大于limit,则只消费limit条数据,如果不足,则全部消费完;

 

容错处理:

1) 获取offsetgetLastOffset

if (response.hasError()),表明有错,打印错误,返回-1

2) 获取offset,决定本次消费的范围getOffsetRange

range[0]:最早的消息的offset,应该是0

range[1]:此刻为止最新消息的offset

由于我们是接着上一次继续消费,所以基本不会使用range[0],而是消费offset.dat中的offsetrange[1]之间的消息;所以最重要的是防止range[1]的值出错;

所以:if (range[1] == -1) ,说明offset值有误,那么再次调用getLastOffset函数,重新尝试一次;

一般情况下不会,因为创建context对象,在构造函数中,实时获取了此刻的leader,之后就调用getoffset,所以短时间内应该不会变化,或有异常;

3) fetchMore

增加了容错,

_response = _consumer.fetch(fetchRequest);

/* simpleconsumer自己没有处理leader broker坏掉的情况,所以需要自己处理 */

if (_response.hasError()) {

Offset无效的处理,选择最多消费一次(出现错误则丢掉部分数据,从最新的开始消费),或者至少消费一次(从offset.dat文件中的offset处继续消费,可能重复消费)的机制:

4) Get()获取每一条消息

//add to message list

message_list.add(new String(messagebytes, "UTF-8") + "\n");

添加换行符,加入message list中;


总结:

至此,此程序可以消费任意多个topic的消息,并追加至以topic+partition命名的hdfs文件内。

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

kafka connect 数据写hdfs详解

源码解读写入状态机实现。 WRITE_STARTED WRITE_PARTITION_PAUSED SHOULD_ROTATE TEMP_FILE_CLOSED WAL_APPENDED FILE_C...

Kafka导入hdfs数据持久化

我们用Flume采集日志信息后,数据进入Kafka。在Kafka之后的选择我们有很多,最典型的就是Flume-ng------Kafka------Storm。当然也可以是Mongo、Elastics...

单线程消费kafka存放到HDFS

Java消费kafka存放HDFS

Tomcat catalina.out文件过大的解决方案整理.

解决Tomcat日志catalina.out文件过大的问题,主要是在相关博客中寻找了一些方案,也留做一个备忘。

Kafka实时流数据经Storm至Hdfs

目前HDFS上日志一部分由MR清洗生成&二次计算,一部分直接从服务器离线上传,但在私有云环境下,离线日志的压缩上传可能会对服务造成性能影响,而且在很多日志已经实时传输到Kafka集群的情况下,考虑Ka...

Linkedin Camus,从Kafka到HDFS的数据传输管道

Preface 本文是对Linkedin-Camus的介绍。内容都是从Camus的github中摘取出来的,详细的内容要看其说明和源码 Introduction of Camus C...

Java数据结构与算法解析(三)——队列与背包

关联文章: Java数据结构与算法解析(一)——表 Java数据结构与算法解析(二)——栈队列基本概念像栈一样,队列也是表。然而,使用队列时插入在一端进行,而删除则在另一端进行。插入的一端称为队尾...

Kafka---数据持久化

今天在学习Kafka(参考文献)的时候,看到由于Kafka是基于JVM的,而Java对象占用空间差不多是数据的两倍并且随着堆中数据量的增加垃圾回收越来越困难,因此如果把数据缓存在内存中会带来严重的GC...

SSIS+数据仓库系列--- 缓慢渐变维度 (Slowly Changing Dimension) 常见的三种类型及原型设计

在从 OLTP 业务数据库向 DW 数据仓库抽取数据的过程中,特别是第一次导入之后的每一次增量抽取往往会遇到这样的问题:业务数据库中的一些数据发生了更改,到底要不要将这些变化也反映到数据仓库中?在数据...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)