flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址

flume 问题无法解析kafka地址 flume对接kafka_kafka_02


一、Kafka对接Flume

既然我们学习了Kafka,那么我们肯定是要用Kafka的,在企业中最常用的流程处理方式如下👇

日志、埋点数据 👉 flume 👉 kafka 👉 flume(根据情景增删该流程) 👉 HDFS

虽然Kafka和Flume对接很简单,但是我们还是记录一下,以免哪天忘了就尴尬了你说是不是呀QAQ,如果小伙伴们对Flume的基本操作有些生疏的,可以去看一下我的另一篇博客 Flume入门解析(一),加强一下对Flume的印象!

好了,废话不多说,我们开始吧!

大致流程为:
监控本地文件  --->  flume  --->  kafka  --->  flume --->  HDFS

Kafka对接Flume时,有两种方式

方式1:常规方式:File Source -> Memory Channel-> Kafka Sink
方式2:其他方式:File Source -> Kafka Channel

方式1👇

第一步:配置Flume
该Flume配置是监控本地文件,传输到Kafka
vim exec2kafka.conf

# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F -c +0 /opt/datas/web.log
a1.sources.r1.shell = /bin/bash -c

# sink
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.bootstrap.servers = broker地址:9092...
a1.sinks.k1.kafka.topic = 主题名
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1

# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
该Flume配置是消费Kafka中的数据,传输到HDFS
vim kafka2hdfs.conf

# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# source
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.channels = c1
a1.sources.r1.batchSize = 5000
a1.sources.r1.batchDurationMillis = 2000
a1.sources.r1.kafka.bootstrap.servers = broker地址:9092...
a1.sources.r1.kafka.topics = 主题名1、主题名2...
a1.sources.r1.kafka.consumer.group.id = 组id

# sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.channel = c1
a1.sinks.k1.hdfs.path = /flume/events/%y-%m-%d/%H%M/%S
a1.sinks.k1.hdfs.filePrefix = events-
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 10
a1.sinks.k1.hdfs.roundUnit = minute

# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
第二步:开启Flume
bin/flume-ng agent -c conf/ -n a1 -f conf/exec2kafka.conf

bin/flume-ng agent -c conf/ -n a1 -f conf/kafka2hdfs.conf
第三步:开启Kafka

bin/kafka-server-start.sh -daemon ./config/server.properties

第四步:向本地文件写入数据然后在HDFS查看数据

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_03


flume 问题无法解析kafka地址 flume对接kafka_kafka_04

可以看到数据已经传输到了HDFS上,大功告成!


方式2👇 (Kafka Channel中存储在Kafka的磁盘中,比内存更可靠)

第一步:配置Flume
该Flume配置是监控本地文件,传输到Kafka
vim exec2kafka.conf

# define
a1.sources = r1
a1.channels = c1

# source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F -c +0 /opt/datas/web.log
a1.sources.r1.shell = /bin/bash -c

# configure channel
a1.channels.c1.type = org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers = broker地址:9092...
a1.channels.c1.kafka.topic = 主题名
a1.channels.c1.parseAsFlumeEvent = false
a1.channels.c1.kafka.consumer.group.id = 消费者组id

# bind
a1.sources.r1.channels = c1
该Flume配置是消费Kafka中的数据,传输到HDFS
vim kafka2hdfs.conf

# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# source
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.channels = c1
a1.sources.r1.batchSize = 5000
a1.sources.r1.batchDurationMillis = 2000
a1.sources.r1.kafka.bootstrap.servers = broker地址:9092...
a1.sources.r1.kafka.topics = 主题名1、主题名2...
a1.sources.r1.kafka.consumer.group.id = 消费者组id

# sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.channel = c1
a1.sinks.k1.hdfs.path = /flume/events/%y-%m-%d/%H%M/%S
a1.sinks.k1.hdfs.filePrefix = events-
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 10
a1.sinks.k1.hdfs.roundUnit = minute

# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
第二步:开启Flume
bin/flume-ng agent -c conf/ -n a1 -f conf/exec2kafka.conf

bin/flume-ng agent -c conf/ -n a1 -f conf/kafka2hdfs.conf
第三步:开启Kafka

bin/kafka-server-start.sh -daemon ./config/server.properties

第四步:向本地文件写入数据然后在HDFS查看数据

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_03


flume 问题无法解析kafka地址 flume对接kafka_kafka_04

可以看到数据已经传输到了HDFS上,大功告成!


二、Kafka自定义分区器

我们知道,Topic是有分区的,所以Producer在发送数据的数据,它是如何知道该把数据发送到哪里去呢?

我们可以在 doSend 方法中看到一个 partition的方法,根据这个方法得出了分区

flume 问题无法解析kafka地址 flume对接kafka_flume_07


我们看一看这个方法内部是如何实现的呢?如下图👇

flume 问题无法解析kafka地址 flume对接kafka_kafka_08


我们看到,第一步它从ProducerRecord 中获取分区,如果你还有影响,可以记得 ProducerRecord 的构造方法正好有一个可以传入分区,如下图👇

flume 问题无法解析kafka地址 flume对接kafka_flume_09


所以我们可以知道,在构建 ProducerRecord 对象的时候可以指定分区,这样就可以把数据发送到Topic的一个分区上,从而不会出现乱序的情况,但这不是我们的重点,我们再来看一下下面的代码我们在构建 ProducerRecord 的时候如果没有传入分区数,则下面的三元表达式肯定不成立,返回的是第二个参数,那第二个参数里面是怎样的呢?如下图👇

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_10


当我们点击进来之后发现是一个接口,这个接口就是我们今天的重点,待会儿再聊,我们先看一下它的实现类,如下图👇

flume 问题无法解析kafka地址 flume对接kafka_hdfs_11


flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_12


这个 DefaultPartitioner 就是我们默认的分区器了,再没有指定分区的情况下,都是走的这个分区器如下就是它的分区方法,一共两个逻辑,有key和没有key的两种情况,有兴趣的可以研究一下!!!

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_13

好了,上面废话了那么多,现在开始进入正题吧!

如果我们觉得它的默认分区器不满足我们的要求,我们也可以自定义分区器的,我们就模仿官方的来写一个试试吧!!!

首先我们知道,自定义一个分区器肯定要继承 Paritioner 接口的

然后在partition内自定义分区逻辑,如下图👇

flume 问题无法解析kafka地址 flume对接kafka_kafka_14


然后编写 Producer 逻辑,向Properties中添加我们的分区器,覆盖默认的

flume 问题无法解析kafka地址 flume对接kafka_数据_15

运行之后得到结果如下图,分区效果实现了!!!

flume 问题无法解析kafka地址 flume对接kafka_flume_16


三、Kafka拦截器

如果我们想对Producer生产的数据进行个性化处理,那这时候该怎么办呢?

没错,就是用拦截器,如下图👇

flume 问题无法解析kafka地址 flume对接kafka_hdfs_17


flume 问题无法解析kafka地址 flume对接kafka_数据_18


flume 问题无法解析kafka地址 flume对接kafka_kafka_19


简单观察源码我们可以发现,有一个ProducerInterceptor的接口,字面意思都可以猜出Producer端的拦截器,所以,我们创建一个类来继承它实现它的对应方法看看效果吧!!!


需求:对Producer生产的数据加上时间戳,并且统计生产的数据成功数量和失败数量

因为有两个需求,为了简单实现解耦,所以创建两个类,实现简单的拦截器链效果

第一个拦截器代码如下👇,在onSend方法中实现我们的自定义逻辑

flume 问题无法解析kafka地址 flume对接kafka_数据_20


第二个拦截器代码如下👇,在onAcknowledgement方法中根据返回的元数据是否为空判断数据发送成功与否

metadata 和 exception:metadata为空,则数据发送失败,exception为空,则数据发送成功

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_21

简单创建生产者

我们在Properties中添加拦截器即可,添加的是拦截器全限定类名哦!

flume 问题无法解析kafka地址 flume对接kafka_hdfs_22

简单创建消费者

flume 问题无法解析kafka地址 flume对接kafka_flume 问题无法解析kafka地址_23

效果如下图👇

flume 问题无法解析kafka地址 flume对接kafka_kafka_24


flume 问题无法解析kafka地址 flume对接kafka_数据_25