Flume

概述

Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的软件

数据采集

  • 数据从无到有的过程
  • 把客观事件通过传感器等工具量化为数据
  • 数据搬运迁移的过程
  • 把数据从一个存储介质传递到另一个存储介质

flume的采集是数据搬运的采集

版本

Flume 0.9X

  • 简称: Flume OG(original generation)
  • 属于Cloudera

Flume 1.X

  • 简称 Flume NG(next generation)
  • 属于Apache

两个版本之间进行了架构重组, 存在较大的差异, 现在常用的是Flume NG

运行机制

Flume核心角色

  • agent, 是一个java进程, 一般运行在日志收集节点

agent内部组件

  • source
  • 采集源
  • 用于跟数据源对接, 获取数据
  • sink
  • 下沉地
  • 将采集的数据传送到下一级agent 或者 存储到目的地
  • channel
  • agent内部的数据传输通道
  • 缓存来自source的数据, 并传递给sink

整个传输过程中, 以event作为基本单元进行传输

  • event包含
  • event header (头信息)
  • event body (消息体)

Flume安装

安装

  • 上传安装包并解压
  • flume-ng-1.6.0-cdh5.14.0.tar.gz
  • 修改配置文件
  • cp flume-env.sh.template flume-env.sh
  • 从模板中拷贝一份进行修改
  • 修改jdk路径
  • export JAVA_HOME=/export/servers/jdk1.8.0_65

根据需求编写采集方案

  • 可参考官方文档

指定采集方案的配置文件, 运行即可

简单案例

1. 监听本地网络端口, 把网络端口的数据采集并输出到console控制台

  1. 编写采集方案
  • 确定组件类型
  • source
  • NetCat TCP Source
  • channel
  • Memory Channel
  • sink
  • Logger Sink (console)
  • 编写采集方案配置文件
  • netcat-logger.conf
  • # 定义这个 agent 中各组件的名字
  • a1.sources = r1
  • a1.sinks = k1
  • a1.channels = c1
  • # 描述/配置 source 组件:r1
  • a1.sources.r1.type = netcat
  • a1.sources.r1.bind = localhost
  • a1.sources.r1.port = 44444
  • # 描述/配置 sink 组件:k1
  • a1.sinks.k1.type = logger
  • # 描述/配置 channel 组件,此处使用是内存缓存的方式
  • a1.channels.c1.type = memory
  • a1.channels.c1.capacity = 1000
  • a1.channels.c1.transactionCapacity = 100
  • # 为source和sink绑定channel
  • a1.sources.r1.channels = c1
  • a1.sinks.k1.channel = c1
  1. 启动flume
  • bin/flume-ng agent --conf conf --conf-file conf/netcat-logger.conf --name a1 -Dflume.root.logger=INFO,console
  • bin/flume-ng agent -c ./conf -f ./conf/netcat-logger.conf -n a1 -Dflume.root.logger=INFO,console
  • 参数说明
  • –conf(-c)
  • 指定flume自身的配置文件所在目录,
    该路径下必须有两个文件
  • flume-env.sh
  • log4j.properties
  • –conf-file(-f)
  • 指定采集方案
  • –name(-n)
  • 指定agent进程名, 注意要和采集方案中的名字对应
  • -Dflume.root.logger=INFO,console
  • 开启日志, 打印在控制台
  1. 通过Telnet进行测试
  • telnet anget-hostname port

2. 服务器的某特定目录下,会不断产生新的文件,每当有新文件出现,就需要把文件采集到 HDFS 中去

  1. 编写采集方案
  • 确定组件类型
  • source
  • Spooling Directory Source
  • channel
  • Memory Channel
  • sink
  • HDFS Sink
  • 编写采集方案配置文件
  • spooldir-hdfs.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1


# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /root/logs2	#注意:不能往监控目中重复丢同名文件
a1.sources.r1.fileHeader = true


# Describe the sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /flume/events/%y-%m-%d/%H%M/
a1.sinks.k1.hdfs.filePrefix = Woodpecker-

#配置时间取整, (目录多长时间切换) 例如: 当前时间为10:58, 则记为10-50
a1.sinks.k1.hdfs.round = true	#是否开启时间取整
a1.sinks.k1.hdfs.roundValue = 10	#取整值
a1.sinks.k1.hdfs.roundUnit = minute	#取整单位

#配置写入hdfs的方式为滚动方式
a1.sinks.k1.hdfs.rollInterval = 3	#按时间滚动的频率, 默认30s
a1.sinks.k1.hdfs.rollSize = 20	#按文件大小滚动, 默认1kb
a1.sinks.k1.hdfs.rollCount = 5	#按event个数滚动, 默认10个


a1.sinks.k1.hdfs.batchSize = 1
a1.sinks.k1.hdfs.useLocalTimeStamp = true
#生成的文件类型,默认是Sequencefile,可用DataStream,则为普通文本
a1.sinks.k1.hdfs.fileType = DataStream


# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000	#该通道中最大的可以存储的 event 数量
a1.channels.c1.transactionCapacity = 100   #每次最大可以从 source 中拿到或者送到 sink 中的 event数量


# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
  • 注意
  • 监听的目录必须提前存在
  • 文件名不能重复
  • 否则服务会中断
  1. 开启日志采集
  • bin/flume-ng agent -c ./conf -f ./conf/spooldir-hdfs.conf -n a1 -Dflume.root.logger=INFO,console
  • 采集结果
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-16VLRMcw-1593321933480)(assets/image-20200628125408707.png)]

3. 日志内容不断增加,需要把追加到日志文件中的数据实时采集到 hdfs

  1. 编写采集方案
  • 确定组件类型
  • source
  • Exec Source
  • channel
  • Memory Channel
  • sink
  • HDFS Sink
  • 编写采集方案配置文件
  • tail-hdfs.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /root/logs/test.log

# Describe the sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /flume/tailout/%y-%m-%d/%H-%M/
a1.sinks.k1.hdfs.filePrefix = Woodpecker-
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 10
a1.sinks.k1.hdfs.roundUnit = minute
a1.sinks.k1.hdfs.rollInterval = 5
a1.sinks.k1.hdfs.rollSize = 1014
a1.sinks.k1.hdfs.rollCount = 3
a1.sinks.k1.hdfs.batchSize = 1
a1.sinks.k1.hdfs.useLocalTimeStamp = true
#生成的文件类型,默认是Sequencefile,可用DataStream,则为普通文本
a1.sinks.k1.hdfs.fileType = DataStream

# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
  1. 启动flume
  • bin/flume-ng agent -c ./conf/ -f ./conf/tail-hdfs.conf -n a1 -Dflume.root.logger=INFO,console
  1. 模拟数据
  • while true;do date >> /root/logs/test.log;sleep 0.5;done
  1. 查看结果
  • 控制台日志
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c53XOCLN-1593321933482)(assets/image-20200628125607627.png)]
  • hdfs上的结果
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95gzYsLv-1593321933483)(assets/image-20200628125614066.png)]

用到的组件

  • source
  • netcat

监听网络端口数据

  • spooldir

监视目录下文件的变化

注意:

被监视的目录必须存在

监视的目录中的文件名不能重复, 否则会报错, 然后停止监视服务

  • exec

执行shell命令, 将命令执行的结果进行收集

tail -f xxx 监控文件尾部情况(主要是文件新增内容)

  • http

监听HTTP的get和psot请求

  • sink
  • HDFS

roll相关配置 控制文件的滚动

round相关配置 控制目录的滚动

  • channel
  • memory channel

高阶特性

1. avro

  • 在串联的flume架构中, 会涉及两级之间跨网络或跨进程传输数据
  • flume专门设计了一套组件用于跨网络通信, 基于avro的rpc协议
  • avro sink
  • avro source
  • 上级的avro sink通过ip、端口决定要发往哪个下级source
    下级avro source绑定本机的ip和端口号, 进行监听, 等待上级sink传递数据
  • 启动顺序
  • 从远离数据源的方向开始启动
  • avro串联成功, 可从日志中看到分别有OPEN, BOUND, CONNECTED信息

2. load-balance 负载均衡

  • 概述
  • 解决单个进程或机器无法响应所有请求, 由多个进程或机器共同处理的场景
  • flume支持的算法

random 随机

round_robin 轮询

  • 注意
  • 当数据量较小, 单个agent能够应付所有请求的情况下, 即便配置了负载均衡, 也无法生效
  • 配置方式
  • 结构图
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQ9irycx-1593321933484)(assets/image-20200628130139497.png)]
  • 确定组件
  • source
  • Avro Source
  • channel
  • Memory Channel
  • sink
  • Avro Sink
  • flume sink processor
  • Load balancing Sink Processor
  • 编写上级采集方案
  • exec-avro.conf
#设置组件名
agent1.channels = c1
agent1.sources = r1
agent1.sinks = k1 k2

#设置下沉组名
agent1.sinkgroups = g1

#设置channel
agent1.channels.c1.type = memory
agent1.channels.c1.capacity = 1000
agent1.channels.c1.transactionCapacity = 100

#设置source
agent1.sources.r1.channels = c1
agent1.sources.r1.type = exec
agent1.sources.r1.command = tail -F /root/logs/123.log

#设置第一个sink
agent1.sinks.k1.channel = c1
agent1.sinks.k1.type = avro
agent1.sinks.k1.hostname = node-2
agent1.sinks.k1.port = 52020

#设置第二个sink
agent1.sinks.k2.channel = c1
agent1.sinks.k2.type = avro
agent1.sinks.k2.hostname = node-3
agent1.sinks.k2.port = 52020

#设置下沉组成员
agent1.sinkgroups.g1.sinks = k1 k2

#设置负载均衡
agent1.sinkgroups.g1.processor.type = load_balance
agent1.sinkgroups.g1.processor.backoff = true	#是否开启黑名单
agent1.sinkgroups.g1.processor.selector = round_robin  #设置负载均衡的算法为轮询, 还支持random(随机)
agent1.sinkgroups.g1.processor.selector.maxTimeOut=10000	#在黑名单放置的超时时间,超时结束时,若仍然无法接收,则超时时间呈指数增长
  • 编写下级采集方案
  • 第一台机器
  • avro-logger.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
a1.sources.r1.type = avro
a1.sources.r1.channels = c1
a1.sources.r1.bind = node-2
a1.sources.r1.port = 52020
# Describe the sink
a1.sinks.k1.type = logger
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
  • 第二台机器
  • avro-logger.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
a1.sources.r1.type = avro
a1.sources.r1.channels = c1
a1.sources.r1.bind = node-3
a1.sources.r1.port = 52020
# Describe the sink
a1.sinks.k1.type = logger
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

3. failover 容错

  • 概述
  • 解决单点故障问题, 防止因为某台机器或进程出现故障而导致整个模块无法工作
  • 整体流程与load-balance类似, 主要区别在于sink processor
  • 确定组件
  • source
  • Avro Source
  • channel
  • Memory Channel
  • sink
  • Avro Sink
  • flume sink processor
  • Failover Sink Processor
  • 具体配置方式参考官方说明文档
  • 注意
  • 在配置容错处理器时, 可以设置优先级, 优先级越大的作为主, 其他的都是备
  • 当主出现故障, 由次优先级顶上
  • 当优先级更高的主故障修复完毕, 重新上线, 则会重新成为主, 之前的主切换为备
  • 如果没有指定优先级,则根据在配置中指定 Sink 的顺序来确定优先级

4. Flume拦截器

  • 概述
  • 拦截器(interceptor)是 Flume 中简单的插件式组件,设置在 source 和 channel 之间
  • source 接收到的 event 事件,在写入 channel 之前,拦截器都可以进行转换或者删除这些事
  • 每个拦截器只处理同一个 source 接收到的事件
  • 分类
  • 内置拦截器
  • timestamp拦截器(时间戳)
  • 功能
  • 在event header插入时间戳
  • 没有使用拦截器
  • Event: { headers:{ } body: timestamp teset }
  • 使用时间戳拦截器
  • Event: { headers:{timestamp=1593165990402} body: timestamp teset }
  • 配置参考官方文档
  • host拦截器(主机名)
  • 功能
  • 在event header插入ip地址或者主机名
  • 核心配置参数
  • a1.sources.r1.interceptors = host
  • a1.sources.r1.interceptors.host.type=host
  • a1.sources.r1.interceptors.host.useIP=false
  • a1.sources.r1.interceptors.timestamp.preserveExisting=true
  • 详细配置参考
  • static拦截器(静态)
  • 功能
  • 可在event header中插入自定义的kv键值对
  • 核心配置参数
  • a1.sources.r1.interceptors = i1
  • a1.sources.r1.interceptors.i1.type = static
  • a1.sources.r1.interceptors.i1.key = datacenter
  • a1.sources.r1.interceptors.i1.value = NEW_YORK
  • 详细配置参考
  • 自定义拦截器
  • 概述
  • 内置拦截器只能实现对event header头信息的修改, 无法对event body中数据内容的修改
  • 日志的数据信息是存储在event body中, 通过自定义拦截器, 可以对其中的内容进行过滤、加密等操作, 减少数据的传输量, 降低存储开销等
  • 自定义拦截器步骤
  1. 自定义拦截器类CustomParameterInterceptor, 实现Interceptor接口
  2. 在 CustomParameterInterceptor 类中定义变量,用于存放 Flume的配置信息
  • 每一行字段间的分隔符 (fields_separator)
  • 通过分隔符分隔后,所需要列字段的下标(indexs)
  • 多个下标使用的分隔符(indexs_separator)
  • 多个下标使用的分隔符(indexs_separator)
  1. 添加 CustomParameterInterceptor 的有参构造方法, 对Flume配置信息变量初始化
  2. 编写具体拦截的方法intercept(), 通常需要编写两个方法, 一个用于单个拦截, 一个用于批量拦截
  3. 实现的接口中有一个内部接口Builder,
    Flume都是通过该接口进行调用, 因此需要实现一个内部类, 用于接收Flume的配置信息
    在内部类的build()方法中, 通过外部类的有参构造, 将Flume的配置信息传递给外部类
  4. 其他相关业务代码编写
  5. 将程序打成jar包, 放到Flume的lib目录下
  • 编写采集方案, 运行即可
  • 自定义拦截器伪代码
public class CustomParameterInterceptor implements Interceptor{
    外部变量1;
    外部变量2;    
    
     //3、执行外部类的构造器
    public CustomParameterInterceptor(变量1,变量2) {
        外部变量1=变量1;
        外部变量2=变量2;
    }  
        
    //4、针对拦截到event 结合用户配置参数 进行业务处理
    public Event intercept(Event event) {
        //拦截器获取到event进行业务逻辑处理的地方
       数据 = event.getbody();
        process(数据 外部变量 )
       event.setboby(修改之后的数据)   
        return event;   
    }
    
     public static class Builder implements Interceptor.Builder {
         内部变量1;
         内部变量2;
         
         //1.通过上下文对象解析采集方案中的属性值  如果用户没有配置  使用默认值
         public void configure(Context context) {
            内部变量1 = context.getString(配置文件值1,默认值)
            内部变量2 = context.getString(配置文件值2,默认值) 
         }
         
         //2.通过内部类build方法 new外部类实例 通过构造方法 把解析属性赋值给外部类属性
         public Interceptor build() {
             return new CustomParameterInterceptor(内部变量1,内部变量2);
         }
     }
}
//在执行flume进行调用的过程中 基于内部类开始执行的
cn.miracle.interceptor.CustomParameterInterceptor$Builder

hdfsyarn聚合日志滚动_ci