日志采集工具之Flume实操-上

一、Flume概述

  1. flume是一个分布式、可靠且可用的系统,用于有效地收集、聚合和将大量来自许多不同来源的日志数据移动到集中式数据存储。

  2. flume的数据流由事件(Event)贯穿始终。事件是Flume的基本数据单位,它携带日志数据(字节数组形式)并且携带有头信息,这些Event由Agent外部的Source生成,当Source捕获事件后会进行特定的格式化,然后Source会把事件推入(单个或多个)Channel中。你可以把Channel看作是一个缓冲区,它将保存事件直到Sink处理完该事件。Sink负责持久化日志或者把事件推向另一个Source。

  3. Agent结构
    flume运行的核心是Agent,flume以agent为最小的独立运行单位。一个agent就是一个jvm。它是一个完整的数据收集工具,含有三个核心组件,分别是source、channel、sink。通过这些组件,Event可以从一个地方流向另一个地方,如下图所示:
    在这里插入图片描述
    二、Flume安装

  4. 具体操作

(1)将apache-flume-1.9.0-bin.tar.gz上传到linux的/opt/software目录下
(2)解压apache-flume-1.9.0-bin.tar.gz到/opt/module/目录下
[yili@hadoop102 software]$ tar -zxf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/
(3)修改apache-flume-1.9.0-bin的名称为flume-1.9.0
[yili@hadoop102 module]$ mv /opt/module/apache-flume-1.9.0-bin /opt/module/flume-1.9.0
(4)将lib文件夹下的guava-11.0.2.jar删除以兼容Hadoop 3.1.3
[yili@hadoop102 module]$ rm /opt/module/flume-1.9.0/lib/guava-11.0.2.jar
注意:删除guava-11.0.2.jar的服务器节点,一定要配置hadoop环境变量。否则会报如下异常。
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Lists
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 1 more
(5)修改conf目录下的log4j.properties配置文件,配置日志文件路径
[yili@hadoop102 conf]$ vim log4j.properties
flume.log.dir=/opt/module/flume-1.9.0/logs 

三、Flume配置概述

  1. 需求分析
    (1) 按照规划,需要将采集的用户行为日志文件分布在hadoop102、hadoop103两台日志服务器,故需要在hadoop102、hadoop103两台节点配置日志采集flume。
    (2)日志采集flume需要采集日志文件内容,并对日志格式(Json)进行校验,然后将校验通过的日志发送到kafka。

  2. 配置选择
    (1)此处可选择TailDirSource和KafkaChannel,并配置日志校验拦截器。

  3. 原因说明
    (1)TailDirSource
    TailDirSource相比ExecSource、SpoolingDirectorySource,有以下的优势:
    1)TailDirSource:断点续传、多目录(可以实时监控目录下文件变化)。Flume1.6以前需要自己自定义Source记录每次读取文件位置,实现断点续传。
    2)ExecSource可以实时监控文件变化,但是在Flume不运行或者Shell命令出错的情况下,数据将会丢失。
    3)SpoolingDirectorySource支持断点续传,但不能实时监控文件变化。
    (2)KafkaChannel
    采用KafkaChannel,省去了Sink,提高了效率。
    1)FileChannel
    数据存储在磁盘中,可靠性高、效率低;
    2)MemoryChannel
    数据存储在内存中,可靠性差、效率高;
    3)KafkaChannel
    数据存储在kafka中,可靠性高、效率高;

  4. 关键配置
    在这里插入图片描述
    四、flume生产者配置实操

  5. 创建flume配置文件

在hadoop102节点的Flume的job目录下创建file_to_kafka.conf
[yili@hadoop104 flume-1.9.0]$ mkdir job
[yili@hadoop104 flume-1.9.0]$ vim job/file_to_kafka.conf 

10.配置文件内容填写:

#定义组件
a1.sources=r1
a1.channels=c1
#配置source
a1.sources.r1.type=TAILDIR
a1.sources.r1.filegroups=f1
a1.sources.r1.filegroups.f1=/opt/module/applog/log/app.*
a1.sources.r1.positionFile=/opt/module/flume-1.9.0/taildir_position.json
#配置拦截器[etl数据清洗、判断json是否完整]
a1.sources.r1.interceptors=i1
a1.sources.r1.interceptors.i1.type=com.yili.flume.interceptor.ETLInterceptor$Builder
#配置channel
a1.channels.c1.type=org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.channels.c1.kafka.topic=topic_log
a1.channels.c1.parseAsFlumeEvent=false
#配置sink(暂时没有)
#拼接组件
a1.sources.r1.channels=c1
  1. 编写Flume拦截器
    (1)创建Maven工程flume-interceptor
    (2)创建包:com.atguigu.flume.interceptor
    (3)在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>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

2)创建JSONUtils类

package com.yili.flume.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class JSONUtils {

    public static void main(String[] args) {
        System.out.println(isJSONValidate("2222"));
    }

    /**
     * Bean对象转JSON
     *
     * @param object
     * @param dataFormatString
     * @return
     */
    public static String beanToJson(Object object, String dataFormatString) {
        if (object != null) {
            if (StringUtils.isEmpty(dataFormatString)) {
                return JSONObject.toJSONString(object);
            }
            return JSON.toJSONStringWithDateFormat(object, dataFormatString);
        } else {
            return null;
        }
    }

    /**
     * Bean对象转JSON
     *
     * @param object
     * @return
     */
    public static String beanToJson(Object object) {
        if (object != null) {
            return JSON.toJSONString(object);
        } else {
            return null;
        }
    }

    /**
     * String转JSON字符串
     *
     * @param key
     * @param value
     * @return
     */
    public static String stringToJsonByFastjson(String key, String value) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        map.put(key, value);
        return beanToJson(map, null);
    }

    /**
     * 将json字符串转换成对象
     *
     * @param json
     * @param clazz
     * @return
     */
    public static Object jsonToBean(String json, Object clazz) {
        if (StringUtils.isEmpty(json) || clazz == null) {
            return null;
        }
        return JSON.parseObject(json, clazz.getClass());
    }

    /**
     * json字符串转map
     *
     * @param json
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> jsonToMap(String json) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        return JSON.parseObject(json, Map.class);
    }

    public static boolean isJSONValidate(String log) {
        try {
            JSON.parse(log);
            return true;
        } catch (JSONException e) {
            return false;
        }
    }
}

3)创建LogInterceptor类

package com.yili.flume.interceptor;

import com.alibaba.fastjson.support.hsf.HSFJSONUtils;
import com.yili.flume.util.JSONUtils;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;

public class ETLInterceptor implements Interceptor {
    @Override
    public void initialize() {

    }

    @Override
    public Event intercept(Event event) {
        //取数据,后进行校验
        //1. 获取数据
        byte[] body = event.getBody();
        String log = new String(body, StandardCharsets.UTF_8);
        //2. 校验数据
        if (JSONUtils.isJSONValidate(log)) {
            return event;
        } else {
            return null;
        }
    }

    @Override
    public List<Event> intercept(List<Event> list) {
        Iterator<Event> iterator = list.iterator();
        while (iterator.hasNext()) {
            Event event = iterator.next();
            if (intercept(event) == null) {
                iterator.remove();
            }
        }
        return list;
    }

    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder {

        @Override
        public Interceptor build() {
            return new ETLInterceptor();
        }

        @Override
        public void configure(Context context) {

        }
    }
}

4)打包
在这里插入图片描述
5)需要先将打好的包放入到hadoop102的/opt/module/flume-1.9.0/lib文件夹下面。

  1. 日志采集Flume测试
1)启动Zookeeper、Kafka集群
2)启动hadoop102的日志采集Flume
[yili@hadoop102 flume-1.9.0]$ bin/flume-ng agent -n a1 -c conf/ -f job/file_to_kafka.conf -Dflume.root.logger=info,console
3)启动一个Kafka的Console-Consumer
[yili@hadoop102 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic topic_log
4)生成模拟数据
[yili@hadoop102 ~]$ lg.sh 
5)观察Kafka消费者是否能消费到数据
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值