大数据-Flume

Flume的快速入门

1、什么是Flume

Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传
输的系统。Flume 基于流式架构,灵活简单。

2、Flume的作用

大数据-Flume_第1张图片
​ 总结:Flume最主要的作用:实时读取服务器本地磁盘的数据,将数据写入到HDFS

3、Flume的基本架构

大数据-Flume_第2张图片

4、Flume架构中的组件

4.1 Agent

Agent 是一个 JVM 进程,它以事件的形式将数据从源头送至目的。Agent 主要有 3 个部分组成,Source、Channel、Sink。

4.2 Source

Source 是负责接收数据到 Flume Agent 的组件。

常见的类型有: avro、thrift、exec、jms、spooling directory、netcat、sequence、generator、syslog、http、legacy、自定义;

常用的类型:

avro source: 接受网络端口中的数据

exec source: tail -f 表示监控的是文件

spooldir source: 监控文件目录的

**Taildir Source:**监控文件目录下的多个文件

总结:

Exec source 适用于监控一个实时追加的文件,但不能保证数据不丢失;

Spooldir Source 能够保证数据不丢失,且能够实现断点续传,但延迟较高,不能实时监控;

Taildir Source 既能够实现断点续传,又可以保证数据不丢失,还能够进行实时监控。

4.3 Channel

Channel 是位于 Source 和 Sink 之间的缓冲区。

Flume 自带三种 Channel:Memory ChannelFile Channel 以及 Kafka Channel

4.4 Sink

Sink 不断地轮询 Channel 中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个 Flume Agent。

常见类型有:hdfs、logger、avro、thrift、ipc、file、HBase、solr、自定义。

常用的类型:

logger Sink: 输出到控制台

Hdfs Sink:输出到HDFS

Kafka Sink:输出到KafKa

4.5 Event

传输单元,Flume 数据传输的基本单元,以 Event 的形式将数据从源头送至目的地。Event 由 Header 和 Body 两部分组成,Header 用来存放该 event 的一些属性,为 K-V 结构,Body 用来存放该条数据,形式为字节数组。

大数据-Flume_第3张图片

5、Flume的事务

大数据-Flume_第4张图片

6、Flume Agent的内部原理
大数据-Flume_第5张图片
重要组件:
1 ) ChannelSelector
ChannelSelector 的作用就是选出 Event 将要被发往哪个 Channel。其共有两种类型,分别是 Replicating(复制)和 Multiplexing(多路复用)。

ReplicatingSelector 会将同一个 Event 发往所有的 Channel,Multiplexing 会根据相应的原则,将不同的 Event 发往不同的 Channel。

2 ) SinkProcessor
SinkProcessor 共 有 三 种 类 型 , 分 别 是 DefaultSinkProcessor 、LoadBalancingSinkProcessor 和 FailoverSinkProcessor、DefaultSinkProcessor 对应的是单个的 Sink,LoadBalancingSinkProcessor 和FailoverSinkProcessor 对应的是 Sink Group,LoadBalancingSinkProcessor 可以实现负载均衡的功能,FailoverSinkProcessor 可以实现故障转移的功能。

7、Flume的拓扑结构

7.1 简单串联

大数据-Flume_第6张图片

这种模式是将多个 flume 顺序连接起来了,从最初的 source 开始到最终 sink 传送的目的存储系统。此模式不建议桥接过多的flume数量,flume数量过多不仅会影响传输速率,而且一旦传输过程中某个节点 flume 宕机,会影响整个传输系统。

7.2 复制和多路复用

大数据-Flume_第7张图片

Flume 支持将事件流向一个或者多个目的地。这种模式可以将相同数据复制到多个channel 中,或者将不同数据分发到不同的 channel 中,sink 可以选择传送到不同的目的地。

7.3 负载均衡和故障转移

大数据-Flume_第8张图片

Flume支持使用将多个sink逻辑上分到一个sink组,sink组配合不同的SinkProcessor可以实现负载均衡和错误恢复的功能。

7.4 集合

大数据-Flume_第9张图片

这种模式是我们最常见的,也非常实用,日常 web 应用通常分布在上百个服务器,大者甚至上千个、上万个服务器。产生的日志,处理起来也非常麻烦。用 flume 的这种组合方式能很好的解决这一问题,每台服务器部署一个 flume 采集日志,传送到一个集中收集日志的flume,再由此 flume 上传到 hdfs、hive、hbase 等,进行日志分析。

8、自定义拦截器 Interceptor

1 ) 案例需求
使用 Flume 采集服务器本地日志,需要按照日志类型的不同,将不同种类的日志发往不同的分析系统。

2 ) 需求分析

在实际的开发中,一台服务器产生的日志类型可能有很多种,不同类型的日志可能需要发送到不同的分析系统。此时会用到 Flume 拓扑结构中的 Multiplexing 结构,Multiplexing的原理是,根据 event 中 Header 的某个 key 的值,将不同的 event 发送到不同的 Channel中,所以我们需要自定义一个 Interceptor,为不同类型的 event 的 Header 中的 key 赋予不同的值。

3 ) 案例代码

package com.it.lkw.intercepter;

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

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 自定义拦截器
 */
public class CustomInterceptor implements Interceptor {
    List<Event> list = new ArrayList<Event>();

    public void initialize() {

    }

    public Event intercept(Event event) {

        // 获取头信息
        Map<String, String> headers = event.getHeaders();
        // 获取body中信息
        String body = new String(event.getBody());

        if (body.contains("info")) {
            headers.put("type", "info");
        } else if (body.contains("error")) {
            headers.put("type", "error");
        }
        return event;
    }

    public List<Event> intercept(List<Event> list) {
        // 清空
        list.clear();
        // 批量处理
        for (Event event : list) {
            list.add(intercept(event));
        }
        return list;
    }

    public void close() {

    }

    public static class Builder implements Interceptor.Builder {
        @Override
        public Interceptor build() {
            return new CustomInterceptor();
        }

        @Override
        public void configure(Context context) {
        }
    }
}

9、自定义 Source

1)介绍
Source 是负责接收数据到 Flume Agent 的组件。Source 组件可以处理各种类型、各种格式的日志数据,包括 avro、thrift、exec、jms、spooling directory、netcat、sequencegenerator、syslog、http、legacy。官方提供的 source 类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些 source。
官方也提供了自定义 source 的接口:
https://flume.apache.org/FlumeDeveloperGuide.html#source 根据官方说明自定义MySource 需要继承 AbstractSource 类并实现 Configurable 和 PollableSource 接口。
实现相应方法:
getBackOffSleepIncrement()//暂不用
getMaxBackOffSleepInterval()//暂不用
configure(Context context)//初始化 context(读取配置文件内容)
process()//获取数据封装成 event 并写入 channel,这个方法将被循环调用。
使用场景:读取 MySQL 数据或者其他文件系统。

2)需求
使用 flume 接收数据,并给每条数据添加前后缀,输出到控制台。前缀可从 flume 配置文件中配置。

大数据-Flume_第10张图片

3)案例代码

package com.it.lkw.source;

import org.apache.flume.Context;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.PollableSource;
import org.apache.flume.conf.Configurable;
import org.apache.flume.event.SimpleEvent;
import org.apache.flume.source.AbstractSource;

import java.util.HashMap;

/**
 *
 * 使用 flume 接收数据,并给每条数据添加前后缀,输出到控制台。前缀可从 flume 配置文
 * 件中配置
 */
public class MySource extends AbstractSource implements
        Configurable, PollableSource {
    private String prefix;
    private Long delay; // 延时时间
    private String subfix;

    /**
     * 读取数据,创建Event,并发送至channel
     * @return
     * @throws EventDeliveryException
     */
    @Override
    public Status process() throws EventDeliveryException {
        try {
            //创建事件头信息
            HashMap<String, String> hearderMap = new HashMap<>();
            //创建事件
            SimpleEvent event = new SimpleEvent();
            //循环封装事件
            for (int i = 0; i < 5; i++) {
                //给事件设置头信息
                event.setHeaders(hearderMap);
                //给事件设置内容
                event.setBody((prefix + "_itboy" + i + "_" + subfix).getBytes());
                //将事件写入 channel
                getChannelProcessor().processEvent(event);
                Thread.sleep(delay);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Status.BACKOFF;
        }
        return Status.READY;
    }

    @Override
    public long getBackOffSleepIncrement() {
        return 0;
    }

    @Override
    public long getMaxBackOffSleepInterval() {
        return 0;
    }

    /**
     * 读取配置文件
     * @param context
     */
    @Override
    public void configure(Context context) {
        prefix = context.getString("prefix", "hello-");
        delay = context.getLong("delay", 0L);
        subfix = context.getString("subfix");
    }
}

9、自定义Sink

1 ) 介绍
Sink 不断地轮询 Channel 中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个 Flume Agent。Sink 是完全事务性的。在从 Channel 批量删除数据之前,每个 Sink 用 Channel 启动一个事务。批量事件一旦成功写出到存储系统或下一个 Flume Agent,Sink 就利用 Channel 提交事务。事务一旦被提交,该 Channel 从自己的内部缓冲区删除事件。

Sink 组件目的地包括 hdfs、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。官方提供的 Sink 类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些 Sink。
官方也提供了自定义 sink 的接口:
https://flume.apache.org/FlumeDeveloperGuide.html#sink 根据官方说明自定义MySink 需要继承 AbstractSink 类并实现 Configurable 接口。
实现相应方法:
configure(Context context)//初始化 context(读取配置文件内容)
process()//从 Channel 读取获取数据(event),这个方法将被循环调用。
使用场景:读取 Channel 数据写入 MySQL 或者其他文件系统。
2 ) 需求
使用 flume 接收数据,并在 Sink 端给每条数据添加前缀和后缀,输出到控制台。前后缀可在 flume 任务配置文件中配置。

3)案例代码

package com.it.lkw.sink;

import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 自定义Sink
 */
public class MySink extends AbstractSink implements Configurable {

    // 创建Logger对象
    private Logger logger = LoggerFactory.getLogger(MySink.class);

    private String prefix;// 前缀
    private String subfix;// 后缀

    /**
     * 读取获取数据
     * @return
     * @throws EventDeliveryException
     */
    @Override
    public Status process() throws EventDeliveryException {
        // 1 状态信息
        Status status = null;
        // 2 获取channel
        Channel channel = getChannel();

        // 3 从channel中获取事务
        Transaction tx = channel.getTransaction();

        // 4 开启事务
        tx.begin();

        try {
            // 5 从channel 中获取事务
            Event event = channel.take();

            if (event != null) {
                // 6 处理数据(打印到控制台)
                logger.info(prefix + new String(event.getBody()) + "-" + subfix);
            }

            // 7 提交
            tx.commit();
            // 8 更改状态信息
            status = Status.READY;
        } catch (ChannelException e) {
            // 9 Catch回滚 更改状态信息
            tx.rollback();
            status = Status.BACKOFF;
            e.printStackTrace();
        } finally {
            // 10 Finally 事务关闭
            tx.close();
        }
        return status;
    }

    // 读取配置文件
    @Override
    public void configure(Context context) {
        context.getString("prefix", "hello-");
        context.getString("subfix");
    }
}

llback();
status = Status.BACKOFF;
e.printStackTrace();
} finally {
// 10 Finally 事务关闭
tx.close();
}
return status;
}

// 读取配置文件
@Override
public void configure(Context context) {
    context.getString("prefix", "hello-");
    context.getString("subfix");
}

}




你可能感兴趣的:(大数据-Flume)