帅气的目录

  • 0、先介绍一个Linux监控文件内容功能
  • 1、Flume简介
  • 2、安装
  • 3、简单使用
  • 3.1、监控单个追加文件
  • 3.2、监控目录下的多个追加文件(并写到HDFS)
  • 3.3、自定义拦截器(Java代码)
  • 4、附录


0、先介绍一个Linux监控文件内容功能

Linux的tail命令可以监控文件内容变化,man tail可查看命令详情

我们开两个窗口,一边使用tail -F b.txt,另一边往文件b.txt追加内容

flume监听文件上传hdfs失败 flume监控文件机制_HDFS


可以看到,追加的内容被实时打印出来了

1、Flume简介

  • 海量日志 采集、聚合、传输 的系统
  • 基于流式架构
  • 入门功能:实时监控【单个追加文件、目录下多个新文件、目录下的多个追加文件】
  • 官方教学:http://flume.apache.org/FlumeUserGuide.html
  • 下载地址:http://archive.apache.org/dist/flume/
官方架构图

flume监听文件上传hdfs失败 flume监控文件机制_flume监听文件上传hdfs失败_02

主要概念

说明

备注

Agent

是一个JVM进程

主要包括【Source、Channel、Sink】

Source

接收数据

例如:监控文件

Channel

缓冲区

可以是:内存 or 磁盘

Sink

输出数据

例如:写到HDFS

Event

数据传输的基本单元

组成:Header(k=v)Body(byte array)

2、安装

本文环境

版本

说明

Java

1.8

预先装好

Hadoop

3.1.3

预先装好

Flume

1.9

待安装,路径:/opt/flume

  1. 环境变量
vi /etc/profile.d/custom.sh
# Flume
export FLUME_HOME=/opt/flume
export PATH=$PATH:$FLUME_HOME/bin
source /etc/profile.d/custom.sh
  1. 解压、改名
tar -zxf apache-flume-1.9.0-bin.tar.gz -C /opt/
cd /opt
mv apache-flume-1.9.0-bin flume
  1. 解决和Hadoop的jar冲突(Hadoop3.1.3的guava版本是27)
cd $FLUME_HOME/lib
mv guava-11.0.2.jar guava-11.0.2.jar.bak
  1. 日志配置(可选)
vi $FLUME_HOME/conf/log4j.properties

flume监听文件上传hdfs失败 flume监控文件机制_HDFS_03

3、简单使用

常用语法:flume-ng <command> [options] ... 常用示例:flume-ng agent -n anent名 -c 配置文件目录 -f 配置文件

大类

名称

说明

命令

agent

运行一个Flume agent

命令

help

显示帮助

命令

version

显示版本

全局选项

--conf <conf>-c <conf>

使用<conf>目录里的配置

agent选项

--name <name>-n <name>

agent名(必须项)

agent选项

--conf-file <file>-f <file>

指定配置文件

3.1、监控单个追加文件

flume监听文件上传hdfs失败 flume监控文件机制_HDFS_04

1 编写Flume代码

cd /root
vi b.flume

exec source

# 定义agent名字:a1

# channel名称
a1.channels = c1
# channel类型:内存(断电可能会丢失数据)
a1.channels.c1.type = memory

# source名称
a1.sources = r1
# source类型
a1.sources.r1.type = exec
# source的exec类型下的Linux命令
a1.sources.r1.command = tail -F /root/b.txt
# source把数据传给哪些channels
a1.sources.r1.channels = c1

# sink名称
a1.sinks = k1
# sink类型:logger是打印到终端,另外可选hdfs、hive、kafka……
a1.sinks.k1.type = logger
# sink接收指定名称的channel(只能接收1个,所以channel没加s)
a1.sinks.k1.channel = c1

2 启动Flume,-Dflume.root.logger=INFO,console是将INFO级别的日志打印到控制台

flume-ng agent \
-n a1 \
-c $FLUME_HOME/conf/ \
-f b.flume \
-Dflume.root.logger=INFO,console

3 开两个窗口,一边追加内容到被监控文件,另一边查看

echo ------------ >> /root/b.txt
echo 111111111111 >> /root/b.txt

3.2、监控目录下的多个追加文件(并写到HDFS)

flume监听文件上传hdfs失败 flume监控文件机制_flume监听文件上传hdfs失败_05

1、创建文件夹

cd /root
mkdir data1 data2

2、编写Flume代码

常用配置

属性

默认值

说明

Taildir Source

filegroups

文件组,空格分隔

Taildir Source

filegroups.<filegroupName>

文件组下的绝对路径,支持正则表达式

HDFS Sink

hdfs.filePrefix

FlumeData

给上传到HDFS的文件添加前缀

HDFS Sink

hdfs.fileSuffix

给上传到HDFS的文件添加后缀

HDFS Sink

hdfs.fileType

SequenceFile

SequenceFile不支持压缩,CompressedStream可压缩并要求设置编码解码器

HDFS Sink

hdfs.codeC

压缩所用的编码解码器

HDFS Sink

hdfs.batchSize

100

积攒多少个 events,才冲洗到HDFS

HDFS Sink

hdfs.idleTimeout

30

每过多少秒生成一个新的文件

HDFS Sink

hdfs.rollCount

10

多少个 events 使文件的滚动,设0就是不按照 events数 滚动

Memory Channel

capacity

100

Channel 最多能容多少个 events

Memory Channel

transactionCapacity

100

Channel 每次汇给 sink 的最大 events数

vi c.flume
# 命名,组件绑定
a3.sources = r3
a3.sinks = k3
a3.channels = c3
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

# channel
a3.channels.c3.type = memory

# Taildir Source
a3.sources.r3.type = TAILDIR
# json格式的文件,记录文件尾部位置,用于断点续传
a3.sources.r3.positionFile = /root/position.json
# 被监控的文件组,可以多目录(单磁盘传输速度有限,多目录分布在多磁盘 可并行)
a3.sources.r3.filegroups = f1 f2
a3.sources.r3.filegroups.f1 = /root/data1/a.txt
a3.sources.r3.filegroups.f2 = /root/data2/.*log.*

# HDFS Sink
a3.sinks.k3.type = hdfs
# 写到HDFS的哪里,可使用时间通配符
a3.sinks.k3.hdfs.path = hdfs://hadoop100:8020/flume/%Y%m%d/%H
# 是否按照时间滚动文件夹
a3.sinks.k3.hdfs.round = true
# 多少时间单位创建一个新的文件夹
a3.sinks.k3.hdfs.roundValue = 2
# 设置滚动的时间单位
a3.sinks.k3.hdfs.roundUnit = minute
# 每个文件的滚动大小,单位byte,建议略小于134217728(HDFS默认块大小为128M)
a3.sinks.k3.hdfs.rollSize = 134217700
# 是否使用本地时间戳
# 不设会报错:Expected timestamp in the Flume event headers, but it was null
a3.sinks.k3.hdfs.useLocalTimeStamp = true
# 设置HDFS文件类型,DataStream不乱码
a3.sinks.k3.hdfs.fileType = DataStream

3、启动Flume

flume-ng agent -n a3 -c $FLUME_HOME/conf/ -f c.flume -Dflume.root.logger=INFO,console

4、往被监控目录写内容

echo aaaa >> data1/a.txt
echo bbbb >> data1/b.txt
echo cccc >> data2/c.log
echo dddd >> data2/d.json
5、查看HDFS

flume监听文件上传hdfs失败 flume监控文件机制_apache_06

3.3、自定义拦截器(Java代码)

1、基于3.1、监控单个追加文件进行修改

flume监听文件上传hdfs失败 flume监控文件机制_flume监听文件上传hdfs失败_07

2、pom.xml配置依赖和插件

<dependencies>
    <!-- Flume;其中scope设置为provided,打包时不用打包Flume,因为可以用服务器的那个Flume -->
    <dependency>
        <groupId>org.apache.flume</groupId>
        <artifactId>flume-ng-core</artifactId>
        <version>1.9.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

3、创建a.b.c.MyInterceptor类,自定义业务逻辑(此处是筛选A开头的数据)

package a.b.c;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.List;

public class MyInterceptor implements Interceptor {
    // 初始化
    @Override
    public void initialize() {}

    // 处理单个Event
    @Override
    public Event intercept(Event event) {
        // 取出数据
        byte[] body = event.getBody();
        String data = new String(body);
        // 业务逻辑:筛选开头为A的数据
        if (data.startsWith("A")) {
            return event;
        } else {
            return null;
        }
    }

    // 处理批次的Event
    @Override
    public List<Event> intercept(List<Event> events) {
        // 过滤空数据
        events.removeIf(event -> intercept(event) == null);
        return events;
    }

    // 关闭
    @Override
    public void close() {}

    public static class Builder implements Interceptor.Builder {
        // 创建自定义拦截器对象
        @Override
        public Interceptor build() {
            return new MyInterceptor();
        }

        // 获取配置
        @Override
        public void configure(Context context) {}
    }
}
4、打包

flume监听文件上传hdfs失败 flume监控文件机制_HDFS_08

5、上传到Flumelib文件夹下,上传后检查一下

ll $FLUME_HOME/lib | grep SNAPSHOT.jar

6、加入拦截器,写全类名+内部类

vi b.flume
# 拦截器(内部类使用$符号)
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = a.b.c.MyInterceptor$Builder

7、开两个窗口,一边追加内容到被监控文件,另一边查看(可以看到:不是A开头的数据会被拦截掉)

echo AAAAAAAAAAAAAAA >> b.txt
echo BBBBBBBBBBBBBBB >> b.txt

4、附录

en

🔉

cn

flume

fluːm

水道

source

sɔːrs

水源;来源

sink

sɪŋk

v. 下沉

transaction

trænˈzækʃn

n. 交易;事务;办理;会报

flush

flʌʃ

v. 使发光;冲洗;使暴露

codec

'kodɛk

编码解码器

trigger

ˈtrɪɡər

n. 触发器;v. 触发

intercept

ˌɪntərˈsept

vt. 拦截;窃听;n. 拦截;[数] 截距;

builder

ˈbɪldər

n. 建筑者;建立者