flume01:简介,配置,自定义,调优

是什么

概述

1、Flume是Cloudera公司开发后来贡献给了Apache的一套分布式的、可靠的、简单且灵活的用于进行日志的收集(collecting)、汇聚(agrregating)和传输(moving)系统
2、 Flume的版本:
Flume-og:Flume0.X版本。在分布式和线程并发上做的并不好
Flume-ng:Flume1.X版本,能够较好的支持线程的并发
3、Flume的版本更新相对稳定,版本更新速度平均是一年到一年半更新一次

基本概念

1、Event: (数据传输单元,每条数据就是一个event)
Flume将收集到每一条日志封装成了一个Event对象,所以一个Event对象就是一条日志 - Flume中流动的是Event
Event本质上就是一个json串,即Flume收集到日志之后,会将日志封装成一个json串。一个Event固定的包含2个部分:headers和body
2、Agent
Agent是Flume构成的基本结构,固定的包含三个组件:Source、Channel和Sink,可以选择是否添加Sinkgroup
三个组件:
Source:从数据源来采集数据
Channel:临时存储数据
Sink:将数据写到目的地

流动模型

1、单级流动
在这里插入图片描述
2、多级流动
在这里插入图片描述
3、扇入
在这里插入图片描述
4、扇出
在这里插入图片描述
5、复杂流动
在这里插入图片描述

怎么用

安装

直接解压即可,然后就可以创建一个data目录,在data目录中创建.conf配置文件了

source

avro source

用于接收从端口序列化过来的数据
在这里插入图片描述
测试:使用flume提供的内置的avro客户端测试
sh flume-ng avro-client -H hadoop01 -p 8090 -c …/conf/ -F a.txt

exec source

收集命令的执行结果
在这里插入图片描述

spooling directory source

监听指定的目录,目录下产生新文件的时候,会采集文件中的内容按行采集
在这里插入图片描述

netcat source

监听某个端口的tcp请求,采集发送到这个端口上的数据
在这里插入图片描述

Sequence Generator Source

会自动产生一系列自增的数据,在实际开发中往往用于前期的测试
在这里插入图片描述

HTTP Source

监听http请求,只能监听POST以及GET方式的请求,通常是监听POST请求。对GET请求的监听不稳定
采集通过http请求发送过来的数据
在这里插入图片描述
通过curl命令发送请求
curl -X POST -d ‘[{“header”:{“class”:“big1910”},“body”:“hello big1910”}]’ http://hadoop01:8090

taildir source

实时监控一批文件,记录文件的消费位置,agent重启也不会有重复消费的问题。
在这里插入图片描述

自定义source

所有Source的顶级接口:Source
需要实现EventDrivenSource或者PollableSource
EventDrivenSource:事件驱动型source。需要自定义线程来获取数据
PollableSource:轮训拉取型Source。主动提供线程来获取数据

引入flume依赖

        <dependency>
            <groupId>org.apache.flume</groupId>
            <artifactId>flume-ng-core</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flume</groupId>
            <artifactId>flume-ng-configuration</artifactId>
            <version>1.7.0</version>
        </dependency>

编写自定义source

package cn.tedu.source;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.EventDrivenSource;
import org.apache.flume.channel.ChannelProcessor;
import org.apache.flume.conf.Configurable;
import org.apache.flume.event.EventBuilder;
import org.apache.flume.source.AbstractSource;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AuthSource extends AbstractSource
        implements EventDrivenSource,Configurable {
    private int step = 1;
    private ExecutorService es;

    @Override
    //配置方法,获取.conf配置文件中的值
    // a1.sources.s1.step = xxx
    public void configure(Context context) {
        //获取用户定义的步长
        String step = context.getString("step");
        if (step != null)
            this.step = Integer.parseInt(step);
    }

    //启动source
    @Override
    public synchronized void start() {
        System.out.println("Source开始启动执行~~~");
        // 创建线程池
        es = Executors.newFixedThreadPool(5);
        //ChannelProcessor 提供了将event放入channel的操作
        ChannelProcessor cp = super.getChannelProcessor();
        // 将采集任务线程提交到线程池,写一个任务放到线程池里面执行
        es.submit(new Add(step, cp));
    }

    @Override
    public synchronized void stop() {
        es.shutdownNow();
        System.out.println("Source执行结束~~~");
    }
}

//EventDrivenSource:需要自己使用线程去抓取数据
class Add implements Runnable {
    private int step;
    private ChannelProcessor cp;
    Add(int step, ChannelProcessor cp) {
        this.step = step;
        this.cp = cp;
    }
    @Override
    public void run() {
        int i = 0;
        while (true) {
            // Flume会将收集的数据封装成Event
            // 构建一个headers
            Map<String, String> headers = new ConcurrentHashMap<>();
            headers.put("time", System.currentTimeMillis() + "");
            byte[] body = (i + "").getBytes();
            Event e = EventBuilder.withBody(body, headers);
            // 需要Event传递给Channel
            cp.processEvent(e);
            i += step;
        }
    }
}

将项目打成jar包
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将打好的jar包上传到flume的lib目录下面
配置.conf文件,运行source即可
在这里插入图片描述
如果是Pollable类型的source会自动的不断调用其中的process方法,所以把业务逻辑写到process方法中即可。

channel

Memory channel

内存型通道,使用内存来暂存数据。读写速度快,但是宕机的话会丢失数据。
capacity:容量,在内存中可以存多少条数据,实际过程中会调大。满了之后阻塞
transactionCapacity:channel一次性向sink发送多少event

File Channel

文件通道,将接收到的数据临时存储在磁盘上。File Channel的读写速度比较慢,但是可靠
dataDIrs可以配置多个目录,用逗号隔开
在这里插入图片描述

JDBC channel

将event存入数据库,慢于内存,快于文件,但是只能支持derby。而且derby数据库是一个嵌入式的数据库,同一时间只能有一个人连接使用。所以这个JDBC channel没啥用。

内存溢出channel

内存溢出通道:先写内存,内存满了往磁盘写

sink

Logger Sink

将数据以日志形式打印。
-Dflume.root.logger=INFO,console 就是设置的打印级别是info,打印在控制台上

File_roll Sink

滚动文件。将收集的数据写到指定的目录下。需要指定滚动时间,不指定的话会每隔30s生成一个小文件
在这里插入图片描述

HDFS Sink

HDFS只能接受三种类型的数据,序列/文本/压缩,配置的时候也需要配置滚动时间,如果不指定会每隔30s生成一个小文件,这就会导致HDFS产生大量的小文件
DataStream表示文本格式
在这里插入图片描述

avro sink

序列化之后写到某个端口,实现多级,扇入,扇出

多级

在这里插入图片描述

扇入

在这里插入图片描述

扇出

在这里插入图片描述

自定义sink

自定义sink需要考虑事务的问题。在这个过程中需要覆盖configure、start、process、stop方法。
flume中是有事务的,takeList和putList都是一个阻塞式双端队列。数据采集端的事务控制在channel上,数据写入时事务控制在sink上。
source到channel之间叫put事务,channel到sink之间叫take事务。put事务中,先将baseSize数量的event放入putList,然后把putList中的event放入channel,成功放入清空putList;提交失败则回滚。take事务也有一个takeList,原理也是一样的。takeList中的event成功发给目的地的就清空,如果发送失败的话就把数据归还给channel。
在这里插入图片描述

package cn.tedu.sink;

import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Map;

// 模拟File_roll Sink
public class AuthSink extends AbstractSink
        implements Sink, Configurable {

    private File file;//存储目录
    private PrintStream ps;

    @Override
    public void configure(Context context) {//从配置文件中获取配置属性
        // 获取属性值
        String dir = context.getString("dir");
        // 判断是否指定了输出的目录
        if (dir == null) {
            throw new NullPointerException("存储的目录路径不能为空!!!");
        }
        file = new File(dir);
    }

    @Override
    public synchronized void start() { //初始化sink
        System.out.println("Sink已经启动~~~");
        // 判断路径是否存在
        if (!file.exists())
            // 如果路径不存在,试着创建这个路径
            file.mkdirs();
        // 初始化流对象
        try {
        //获取输出流,文件流
            ps = new PrintStream(file.getPath() + "/" + System.currentTimeMillis());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        super.start();
    }

    @Override
    public Status process() { //process会被不断调用

        // 获取Channel
        Channel c = super.getChannel();
        // 需要考虑事务,获取Transaction
        Transaction t = c.getTransaction();
        // sink端开启事务
        t.begin();
        // 创建Event
        Event e;
        try {
            while ((e = c.take()) != null) { //c.take拿一条信息,可能不止一条数据
                Map<String, String> headers = e.getHeaders(); //拿到event中的headers
                byte[] body = e.getBody(); //拿到body
                ps.println("headers:"); //写出headers
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    ps.println("\t" + entry.getKey() + ":" + entry.getValue()); // 向文件中写入headers的键值对
                }
                ps.println("body:");
                ps.println("\t" + new String(body)); //event中的body是二进制
            }
            t.commit(); //sink成功处理了数据后事务提交
        } catch (Exception ex) {
            t.rollback();//发生异常时,回滚
            ex.printStackTrace();
            return Status.BACKOFF;
        } finally {
            t.close(); //关闭事务
        }
        return Status.READY; //写成功了
    }

    @Override
    public synchronized void stop() { //停止sink时资源回收
        ps.close();
        System.out.println("Sink已经执行完了");
        super.stop();
    }
}

将sink打包ReBuild,传入lib目录下面
在这里插入图片描述

source上的选择器和拦截器

seletor的两种模式

默认使用的是复制模式
replicating(复制模式):每一个channel得到的数据都是相同的
multiplexing(路由模式/多路复用模式):选择event发送给哪一个channel

配置举例

在这里插入图片描述

拦截器(Interceptor)

配置在source上,可以配置多个拦截器,可以配置顺序,形成拦截器链

Timestamp Interceptor

拦截event并处理,在headers中添加一个timestamp字段。
在这里插入图片描述
结合HDFS Sink使用,可以实现按天收集的效果
在这里插入图片描述

Host Interceptor

在headers中添加一个host字段,表示当前主机的IP地址
在这里插入图片描述

Static Interceptor

在headers中添加一个指定的字段,键值对
在这里插入图片描述

UUID Interceptor

在headers中添加一个id,作用往往是标记数据的唯一性,保证数据不重复
在这里插入图片描述

Search And Replace Interceptor

会根据指定的正则表达式去搜索body中的数据,将符合正则格式的数据进行替换
在这里插入图片描述

Regex Filtering Interceptor

需要指定一个正则表达式,只要符合正则表达式格式的event就会被拦截掉
在这里插入图片描述

Sink Group

允许用户将多个sink绑定在一起,实现负载均衡或者failover

failover sink processor

failover的特点是在使用的时候需要指定优先级,只要优先级高的Sink存活,那么优先级的低的Sink就收不到数据
基于扇出结构配置
maxpenalty=10000表示保留10000个数据,当k1挂了之后,会将前面发送的10000条数据再发给新的sink
在这里插入图片描述
还要配置两个sink,以及配置source,channel,sink之间的关系

Load Balancing Sink Processor

基于扇出,将数据轮询或者随机的发给多个chanel,实际上不好用,LB Sink Group

a1.sinkgroups=g1
a1.sinkgroups.g1.sinks=s1 s2
a1.sinkgroups.g1.processor.type=load_balance
a1.sinkgroups.g1.processor.selector=round_robin # round_robin(轮叫调度)random(随机) hash mode

#为channel 绑定 source和sink
a1.sources.r1.channels=c1 c2
a1.sinks.s1.channel=c1
a1.sinks.s2.channel=c2

集群监控

ganglia:集群监控

原理

调优

1、batchSize:决定source一次交给channel的event数量,适当调大参数可以提高source搬运event到channel的能力,sink上的这个参数表示sink一次性读取的event条数,适当调大可以提高sink从channel搬运数据的能力。transactionCapacity数量要大于batchSize数量

flume数据会不会丢失

使用memory channel的时候宕机时数据会丢失

flume

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值