flume

发布于:2025-02-24 ⋅ 阅读:(14) ⋅ 点赞:(0)

Flume是一个高可用,高可靠,分布式的海量日志采集、聚合和传输的系统,能够有效的收集、聚合、移动大量的日志数据。它可以将来自不同数据源(如日志文件、消息队列、网络流等)的数据高效地传输到集中式存储系统(如HDFS、HBase、Kafka等)。

Flume 的核心概念是 Agent,每个 Agent 由三个组件组成,可以理解为一个大自然的搬运工:

  • Source:数据来源(如日志文件、Kafka、HTTP请求等)。

  • Channel:数据缓存(如内存、文件、JDBC等)。

  • Sink:数据目的地(如HDFS、Kafka、HBase等)。

Agent就是我们使用Flume启动的一个代理,它是一个持续传输数据的服务,数据在Agent内部
的这些组件之间传输的基本单位是Event,Event是一个对象,它里面包含的既有我们采集到的原始的数据,还有一个header属性,header属性是一个key-value结构

使用hdfs.useLocalTimeStamp(默认为false,需要改为true)或者时间拦截器,header里面会有日期时间。

Event中包含header和body;
body是采集到的那一行记录的原始内容
header类型为Map<String, String>,里面可以存储一些属性信息,方便Channel和Sink使用

复杂场景01:

复杂场景02:

Flume中多个Agent之间是可以连通的,只需要让前面Agent的sink组件把数据写到下一个Agent的source组件中即可。

Source

Source:数据源:通过source组件可以指定让Flume读取哪里的数据,然后将数据传递给后面的
channel,数据可以自定义。

常用的组件:

Exec Source:实现文件监控,可以实时监控文件中的新增内容,类似于linux中的tail -f 效果。
在这需要注意 tail -F 和 tail -f 的区别

tail -F
等同于–follow=name --retry,根据文件名进行追踪,并保持重试,即该文件被删除或改名后,再次创建相同的文件名,会继续追踪

tail -f
等同于–follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止

应用场景
在实际工作中我们的日志数据一般都会通过log4j记录,log4j产生的日志文件名称是固定的,每天定时给文件重命名,假设默认log4j会向access.log文件中写日志,每当凌晨0点的时候,log4j都会对文件进行重命名,在access后面添加昨天的日期,然后再创建新的access.log记录当天的新增日志数据。这个时候如果想要一直监控access.log文件中的新增日志数据的话,就需要使用tail -F


NetCat TCP/UDP Source: 采集指定端口(tcp、udp)的数据,可以读取流经端口的每一行数据
Spooling Directory Source:采集文件夹里新增的文件
Kafka Source:从Kafka消息队列中采集数据

Channel

接受Source发出的数据,可以把channel理解为一个临时存储数据的管道

常见的组件:

Memory Channel:使用内存作为数据的存储
        优点是效率高,因为就不涉及磁盘IO
        缺点有两个:
                1:可能会丢数据,如果Flume的agent挂了,那么channel中的数据就丢失了。
                2:内存是有限的,会存在内存不够用的情况

File Channel:使用文件来作为数据的存储

        优点是数据不会丢失
        缺点是效率相对内存来说会有点慢,但是这个慢并没有我们想象中的那么慢


Spillable Memory Channel:使用内存和文件作为数据存储,即先把数据存到内存中,如果内存中数据达到阈值再flush到文件中

        优点:解决了内存不够用的问题。

        缺点:还是存在数据丢失的风险

Sink

Sink:从Channel中读取数据并存储到指定目的地

Channel中的数据直到进入目的地才会被删除,当Sink写入目的地失败后,可以自动重写,不会造成数据丢失,有一个事务保证的。 

常见的组件

Logger Sink:将数据作为日志处理,可以选择打印到控制台或者写到文件中,测试的时候使用
HDFS Sink:将数据传输到HDFS中,这个是比较常见的,主要针对离线计算的场景
Kafka Sink:将数据发送到kafka消息队列中,这个也是比较常见的,主要针对实时计算场景,数据不落盘,实时传输,最后使用实时计算框架直接处理。 

配置Flume

配置Flume agent的主要流程是这样的
1. 给每个组件起名字
2. 配置每个组件的相关参数
3. 把它们联通起来

# 起名字
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# 指定类型、ip、端口,相当于一个socket服务端,监听客户端的数据
a1.sources.r1.type = netcat

# 如果通过bind参数指定某一个ip的话,表示就只监听通过这个ip发送过来的数据了,这样会有局限性,所以可以指定0.0.0.0。
a1.sources.r1.bind = localhost

# 这个agent 对外的 端口号
a1.sources.r1.port = 44444
# sink 的type 必填
a1.sinks.k1.type = logger
# channels 的type 必填
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
#Bindthesource andsink tothechannel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

高级组件

 Source Interceptors:Source可以指定一个或者多个拦截器按先后顺序依次对采集到的数据进行处理。
Channel Selectors:Source发往多个Channel的策略设置,如果source后面接了多个channel,到底是给所有的channel都发,还是根据规则发送到不同channel,这些是由Channel Selectors来控制的
Sink Processors:Sink 发送数据的策略设置,一个channel后面可以接多个sink,channel中的数据是被哪个sink获取,这个是由Sink Processors控制的

Source Interceptors

常见的拦截器:

Timestamp Interceptor:向event中的header里面添加timestamp 时间戳信息


Host Interceptor:向event中的header里面添加host属性,host的值为当前机器的主机或者ip

Search and Replace Interceptor:根据指定的规则查询Event中body里面的数据,然后进行替换,这个拦截器会修改event中body的值,也就是会修改原始采集到的数据内容


Static Interceptor:向event中的header里面添加固定的key和value


Regex Extractor Interceptor:根据指定的规则从Event中的body里面抽取数据,生成key和value,再把key和value添加到header中

Channel Selectors

Channel Selectors类型包括:Replicating Channel Selector (默认)、Multiplexing Channel Selector

Replicating Channel Selector:

官方示例

source的数据会发往c1、c2、c3这三个channle中,可以保证c1、c2一定能接收到所有数据,但是c3就无法保证了,因为C3 是可选的,对C3的写入失败,是不会触发事务的。

Multiplexing Channel Selector:它表示会根据Event中header里面的值将Event发往不同的Channel

官方示例:

如果state属性的值是CZ,则发送给c1

如果state属性的值是US,则发送给c2 c3

如果state属性的值是其它值,则发送给c4

 Sink Processors

Sink Processors类型包括这三种:Default Sink Processor、Load balancing Sink Processor和FailoverSink Processor


DefaultSink Processor是默认的,不用配置sinkgroup,一个channel后面接一个sink的形式。
Load balancing Sink Processor是负载均衡处理器,一个channle后面可以接多个sink,这多个sink属于一个sink group,根据指定的算法进行轮询或者随机发送,减轻单个sink的压力。可以解决Agent单点故障的问题 。


Failover Sink Processor是故障转移处理器,一个channle后面可以接多个sink,这多个sink属于一个sink group,按照sink的优先级,默认先让优先级高的sink来处理数据,如果这个sink出现了故障,则用优先级低一点的sink处理数据,可以保证数据不丢失。 这两个sink正常情况下只有一个干活,另一个是不干活的,可以理解为主从架构。

Flume优化

调整Flume进程的内存大小,建议设置1G~2G,太小的话会导致频繁GC
因为Flume进程也是基于Java的,所以就涉及到进程的内存设置,一般建议启动的单个Flume进程(或者说单个Agent)内存设置为1G~2G,内存太小的话会频繁GC,影响Agent的执行效率。


那具体设置多少合适呢?这个需求需要根据Agent读取的数据量的大小和速度有关系,所以需要具体情况具体分析,当Flume的Agent启动之后,对应就会启动一个进程,我们可以通过jstat -gcutil PID 1000来看看这个进程GC的信息,每一秒钟刷新一次,如果GC次数增长过快,说明内存不够用。

如果需要调整Flume进程内存的话,需要调整 flume-env.s h脚本中的 JAVA_OPTS 参数把 export JAVA_OPTS 参数前面的#号去掉才会生效。

# 建议这里的 Xms 和 Xmx 设置为一样大,避免进行内存交换,内存交换也比较消耗性能。

export JAVA_OPTS="-Xms1024m -Xmx1024m -Dcom.sun.management.jmxremote"