帅气的目录
- 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
追加内容可以看到,追加的内容被实时打印出来了
1、Flume简介
- 海量日志 采集、聚合、传输 的系统
- 基于流式架构
- 入门功能:实时监控【单个追加文件、目录下多个新文件、目录下的多个追加文件】
- 官方教学:http://flume.apache.org/FlumeUserGuide.html
- 下载地址:http://archive.apache.org/dist/flume/
官方架构图
主要概念 | 说明 | 备注 |
Agent | 是一个JVM进程 | 主要包括【Source、Channel、Sink】 |
Source | 接收数据 | 例如:监控文件 |
Channel | 缓冲区 | 可以是:内存 or 磁盘 |
Sink | 输出数据 | 例如:写到HDFS |
Event | 数据传输的基本单元 | 组成: |
2、安装
本文环境 | 版本 | 说明 |
Java | 1.8 | 预先装好 |
Hadoop | 3.1.3 | 预先装好 |
Flume | 1.9 | 待安装,路径: |
- 环境变量
vi /etc/profile.d/custom.sh
# Flume
export FLUME_HOME=/opt/flume
export PATH=$PATH:$FLUME_HOME/bin
source /etc/profile.d/custom.sh
- 解压、改名
tar -zxf apache-flume-1.9.0-bin.tar.gz -C /opt/
cd /opt
mv apache-flume-1.9.0-bin flume
- 解决和Hadoop的jar冲突(Hadoop3.1.3的
guava
版本是27)
cd $FLUME_HOME/lib
mv guava-11.0.2.jar guava-11.0.2.jar.bak
- 日志配置(可选)
vi $FLUME_HOME/conf/log4j.properties
3、简单使用
常用语法:flume-ng <command> [options] ...
常用示例:flume-ng agent -n anent名 -c 配置文件目录 -f 配置文件
大类 | 名称 | 说明 |
命令 |
| 运行一个 |
命令 |
| 显示帮助 |
命令 |
| 显示版本 |
全局选项 |
| 使用 |
|
|
|
|
| 指定配置文件 |
3.1、监控单个追加文件
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)
1、创建文件夹
cd /root
mkdir data1 data2
2、编写Flume代码
常用配置 | 属性 | 默认值 | 说明 |
Taildir Source |
| 文件组,空格分隔 | |
Taildir Source |
| 文件组下的绝对路径,支持正则表达式 | |
HDFS Sink |
|
| 给上传到HDFS的文件添加前缀 |
HDFS Sink |
| 给上传到HDFS的文件添加后缀 | |
HDFS Sink |
|
|
|
HDFS Sink |
| 压缩所用的编码解码器 | |
HDFS Sink |
| 100 | 积攒多少个 events,才冲洗到HDFS |
HDFS Sink |
| 30 | 每过多少秒生成一个新的文件 |
HDFS Sink |
| 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
3.3、自定义拦截器(Java代码)
1、基于3.1、监控单个追加文件
进行修改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、打包5、上传到Flume的
lib
文件夹下,上传后检查一下
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. 建筑者;建立者 |