一、写flume的步骤
1.0.0 Flume 事务
1.0.1 Flume Agent内部原理
图1
1.1 画拓扑图
总结:一个channel只能输出一个结果文件。
一个flume agent 由 source + channel + sink 构成,类比于mapper + shuffer + reducer。
1.1.1 确定source类型
常用类型: 1) Avro: 用于Flume agent 之间的数据源传递 2) NetCat: 用于监听端口 3)Exec 用于执行linux中的操作指令 4) Spooling Directory: 用于监视文件或目录 5) Taildir: 用于监视文件或目录,同时支持追加的监听 6) Sequence Generator:一个简单的序列发生器,不断的产生事件,值是从0开始每次递增1。主要用来测试。 7) Kafka:支持从Kafka指定的topic中读取数据 总结 ,3/4/5三种方式,最常用的是5,适合用于监听多个实时追加的文件,并且能够实现断点续传。 tips: 1:TailDir Source 是否支持递归遍历文件夹读取文件? -->不支持。自定义,递归遍历文件夹 + 读取文件 2:TailDir Source实现断点续传的原因: --> Taildir Source维护了一个json格式的position File,其会定期的往position File中更新每个文件读取到的最新的位置,因此能够实现断点续传。Position File的格式如下: {"inode":2496272,"pos":12,"file":"/opt/module/flume/files1/file1.txt"} {"inode":2496275,"pos":12,"file":"/opt/module/flume/files1/file2.txt"} TailDir Source重复消费数据的原因: Linux中储存文件元数据的区域就叫做inode,每个inode都有一个号码,操作系统用inode号码来识别不同的文件,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。TailDir source使用inode和文件的全路径一起识别同一个文件(正则表达式匹配文件名),所以修改文件名之后如果表达式也能够匹配上,会再重新读取一份文件的数据。 log4j: 2022-03-12 server.log 325 2022-03-13 server.log 0 server.log.2022-03-12 623 解决方案一:日志不更名 ------ 换不更名日志打印框架 解决方案二: /xxx/xxx/server.log × 解决方案三:只看iNode值 修改源码
1.1.2 确定channel selector 的选择器
1)replicating channel selector:复制,每个channel发一份数据 -- 默认的选择器 2) multiplexing channel selector : 多路复用,根据配置文件,指定source源获取的数据发往一个或多个channel
1.1.3 channel类型(Flume优化-->File Channel)
1) Memory Channel : 加载在内存中,存在数据丢失的风险,可靠性差,传输速度快,默认容量100个event -- 学习阶段使用此参数 2) File Channel :写入磁盘,可靠性高,传输速度低,默认容量,100万event tips: Flume优化--> FileChannel可以通过配置dataDirs指向多个路径,每个路径对应不同的硬盘,增大Flume吞吐量。
1.1.4 sinkprocessor选型
1) DefaultSinkProcessor(默认1对1):对应的是单个的Sink 2) LoadBalancingSinkProcessor(负载均衡) :对应的是Sink Group,可以实现负载均衡的功能 3) FailoverSinkProcessor(故障转移) :对应的是Sink Group,容错功能,先指定一个sink,所有的数据都走指定的sink,当sink故障以后,其他的sink顶上,如果开始sink恢复了,那么数据继续走原有指定的sink。
1.1.5 确定sink的类型
常使用的类型有: 1) avro: 用于输出到下一个Flume Agent ,一个开源的序列化框架 2) hdfs: 输出到hdfs 3) fill_roll: 输出到本地 4) logger: 输出到控制台 5) hbase: 输出到hbase 6)hive:将文本数据或JSON数据输出到Hive表或分区-->数据会被映射到Hive表中的相应列
1.1.6 拓扑例图
图3
1.17 拦截器(拦截器可以不用吗?)
1:ETL拦截器-->过滤脏数据 2:TimeStamp拦截器-->防止零点漂移,即前一天23:58:59的数据由于传输过程的延迟进入第二天的文件目录下 tips: 给每条从kafka里获取到的数据加上一个header,key为timestamp,value为日志里面的ts字段的值(毫秒级时间戳)-->可以保证当天生成的日志数据一定会进入hdfs当天的目录下 自定义拦截器步骤 (1)实现 Interceptor (2)重写四个方法 initialize 初始化 public Event intercept(Event event) 处理单个Event public List<Event> intercept(List<Event> events) 处理多个Event,在这个方法中调用Event intercept(Event event) close 方法 (3)静态内部类,实现Interceptor.Builder tips: -->1:拦截器可以不用吗?-->可以不用;需要在数仓下一级hive的dwd层和SparkSteaming里面处理 优势:只处理一次,轻度处理; 劣势:影响性能,不适合做实时推荐这种对实时要求比较高的场景。 -->2:采用两个拦截器的优缺点-->优点:模块化开发和可移植性; 缺点:性能会低一些。
1.17.1 ETL拦截器--TimeStamp拦截器的编写
pom.xml-->需要导入的相关依赖: <dependencies> <dependency> <groupId>org.apache.flume</groupId> <artifactId>flume-ng-core</artifactId> <version>1.9.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration>