3-Flume之拦截器与GangLia监控

Flume

Interceptor

概述

  1. Interceptor(拦截器)本身是Source的子组件之一,可以对数据进行拦截、过滤、替换等操作
  2. 不同于Selector,一个Source上可以配置多个Interceptor,构成拦截器链。需要注意的是,后一个拦截器不能和前一个拦截器的规则相反!

Timestamp Interceptor

  1. 在Event的headers中添加一个timestamp字段来表示数据被收集的时间戳(单位是毫秒!)

  2. 案例:Event的header中自动添加上时间戳

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    # 给拦截器起名
    a1.sources.s1.interceptors = i1
    # 配置Timestamp Interceptor
    # 类型必须是timestamp
    a1.sources.s1.interceptors.i1.type = timestamp
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1
  3. Timestamp Interceptor结合HDFS Sink可以实现数据的按时间段存放。文件名后会添加上年月日,并且每日的Event输出到当天对应的文件中。

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    a1.sources.s1.interceptors = i1
    a1.sources.s1.interceptors.i1.type = timestamp
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = hdfs
    a1.sinks.k1.hdfs.path = hdfs://hadoop01:9000/flume_data/logdate=%Y-%m-%d
    a1.sinks.k1.hdfs.rollInterval = 3600
    a1.sinks.k1.hdfs.rollSize = 134217728
    a1.sinks.k1.hdfs.rollCount = 1000000000
    a1.sinks.k1.hdfs.fileType = DataStream
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

Host Interceptor

  1. 在Event的headers中添加一个host字段,用于标记这个数据的来源主机

  2. 案例

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    # 给拦截器起名。多个拦截器的命名必须在一行。不能写在两行
    a1.sources.s1.interceptors = i1 i2
    # 配置Timestamp Interceptor
    # 类型必须是timestamp
    a1.sources.s1.interceptors.i1.type = timestamp
    # 配置Host Interceptor
    # 类型必须是host
    a1.sources.s1.interceptors.i2.type = host
    # 使用IP还是主机名
    a1.sources.s1.interceptors.i2.useIP = false
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

Static Interceptor

  1. 在Event的headers中添加指定的字段以及指定的值,实际过程中用于做标记

  2. 案例 Event的header中自动添加 class:flume这一key value

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    # 给拦截器起名
    a1.sources.s1.interceptors = i1 i2 i3
    # 配置Timestamp Interceptor
    # 类型必须是timestamp
    a1.sources.s1.interceptors.i1.type = timestamp
    # 配置Host Interceptor
    # 类型必须是host
    a1.sources.s1.interceptors.i2.type = host
    # 使用IP还是主机名
    a1.sources.s1.interceptors.i2.useIP = true
    # 配置Static Interceptor
    # 类型必须是static
    a1.sources.s1.interceptors.i3.type = static
    # 指定键
    a1.sources.s1.interceptors.i3.key = class
    # 指定值
    a1.sources.s1.interceptors.i3.value = flume
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

UUID Interceptor

  1. UUID计算产生一串编号,由于编号位数比较多,因此几乎不太可能产生重复的编号,因此实际过程中经常使用UUID作为唯一标记

  2. UUID Interceptor是在Event的headers中添加一个id字段来标记这个数据的唯一性

  3. 案例

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    # 给拦截器起名 
    a1.sources.s1.interceptors = i1 i2 i3 i4
    # 配置Timestamp Interceptor
    # 类型必须是timestamp
    a1.sources.s1.interceptors.i1.type = timestamp
    # 配置Host Interceptor
    # 类型必须是host
    a1.sources.s1.interceptors.i2.type = host
    # 使用IP还是主机名
    a1.sources.s1.interceptors.i2.useIP = true
    # 配置Static Interceptor
    # 类型必须是static
    a1.sources.s1.interceptors.i3.type = static
    # 指定键
    a1.sources.s1.interceptors.i3.key = class
    # 指定值
    a1.sources.s1.interceptors.i3.value = flume
    # 配置UUID Interceptor
    # 类型是UUIDInterceptor$Builder
    a1.sources.s1.interceptors.i4.type = org.apache.flume.sink.solr.morphline.UUIDInterceptor$Builder
    
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1
  1. 在使用的时候需要指定正则表达式,会将满足正则表达式的数据替换为指定形式的数据。在替换的时候,只替换body中的数据,不替换headers中的数据!!!

  2. 案例

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = http
    a1.sources.s1.port = 8888
    a1.sources.s1.interceptors = i1
    # 类型必须是search_replace
    a1.sources.s1.interceptors.i1.type = search_replace
    # 指定正则表达式
    a1.sources.s1.interceptors.i1.searchPattern = [0-9]
    # 指定替换形式
    a1.sources.s1.interceptors.i1.replaceString = *
    
    a1.channels.c1.type = memory
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

Regex Filtering Interceptor

  1. 在使用的时候需要指定正则表达式。通过属性excludeEvents来决定过滤方式。如果excludeEvents的值为true,表示符合正则表达式形式的数据会被过滤掉;如果excludeEvents的值为false,那么表示不符合正则表达式形式的数据会被过滤掉

  2. 案例

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8888
    a1.sources.s1.interceptors = i1
    # 类型必须是regex_filter
    a1.sources.s1.interceptors.i1.type = regex_filter
    # 指定正则表达式
    a1.sources.s1.interceptors.i1.regex = .*[0-9].*
    # 指定过滤方式
    a1.sources.s1.interceptors.i1.excludeEvents = true
    
    a1.channels.c1.type = memory
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

Custom Interceptor

  1. 定义一个类实现Interceptor接口,同时还需要提供内部类Builder
java 复制代码
//模拟TimeStamp
public class AuthInterceptor implements Interceptor {


    @Override
    public void initialize() {

    }

    //单条处理
    @Override
    public Event intercept(Event event){

        Map<String, String> headers = event.getHeaders();
        if(headers.containsKey("time")||headers.containsKey("timestamp"))  return event;
        //时间格式可自定义
        headers.put("time", String.valueOf(System.currentTimeMillis()));
        return event;
    }

  
    //按批处理
    @Override
    public List<Event> intercept(List<Event> list) {
        // 定义集合存储处理之后的数据
        List<Event> es = new ArrayList<>();
        for (Event event : es) {
            Event e = intercept(event);
            es.add(e);
        }
        return es;
    }

    @Override
    public void close() {

    }


//这个权限修饰符手动改为public  。  默认为default,外部程序访问不到
public static class AuthBuilder implements Builder {

    // 通过这个函数来获取当前拦截器对象
    @Override
    public Interceptor build() {
        return new AuthInterceptor();
    }

    // 获取配置
    @Override
    public void configure(Context context) {
    }
}
}
  1. 打成jar包,然后放到Flume的lib目录下

    sh 复制代码
    cd /opt/software/flume-1.11.0/lib/
    rz
  2. 格式文件

    sh 复制代码
    cd ../data

    在文件中添加

    properties 复制代码
    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8080
    a1.sources.s1.interceptors = i1
    a1.sources.s1.interceptors.i1.type = com.fesco.in.AuthInterceptor$AuthBuilder
    
    a1.channels.c1.type = memory
    a1.channels.c1.capacity = 10000
    a1.channels.c1.transactionCapacity = 1000
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1

**拦截器的功能:**自动给headers加时间戳。将events按时间在channel中存储在不同文件。给Headers中自动添加该条events的来源主机号;自定义一对kv添加到headers中。将body中的内容按正则匹配并调换。 将body中的内容过滤。 生成UUID唯一标识。

其他

执行流程

  1. Source采集数据,数据被采集之后,会交给ChannelProcessor来处理
  2. ChannelProcessor收到数据之后,会将数据交给Interceptor来进行过滤、拦截、替换等操作。需要注意的是,可以存在多个Interceptor,构成拦截器链
  3. Interceptor处理完数据之后,会将数据交给Selector来进行分发。Selector有3种模式:replicatingmultipexingload balancing。根据指定的模式,将数据分发给对应的Channel
  4. Channel收到数据之后,会将数据推送给SinkProcessor。SinkProcessor本质上是一个SinkGroup,需要将一个或者多个Sink绑定到一个组中,支持三种模式:defaultfailoverload balancing
  5. SinkProcessor收到数据之后,将数据按照指定模式推送给Sink,Sink将数据写到目的地

扩展:Flume监控 - Ganglia

概述
  1. 实际过程中,可以使用Ganglia监控Flume的数据流。Ganglia是Berkeley发起的一个开源的集群监控项目,可以检测数以千计的节点的性能
  2. Ganglia包含三个模块
    1. gmond(Ganglia Monitoring Daemon):轻量级的监控服务,需要监控哪一个节点的性能,就在这个节点上安装gmond服务,可以监控当前节点(系统)的各种指标数据:CPU、内存、磁盘、网络等信息
    2. gmetad(Ganglia Meta Daemon):轻量级的汇合服务,可以将监控信息以RRD格式来存储到磁盘上
    3. gweb(Ganglia Web):Ganglia提供的轻量级的可视化服务,本身是使用PHP来开发的,提供了WEB页面,能够使得用户较为直观和简便的查看到节点的性能
安装
  1. 三个节点上都需要安装httpd和php服务

    sh 复制代码
    yum -y install httpd php
  2. 三个节点上都需要安装rrd服务

    sh 复制代码
    yum -y install rrdtool perl-rrdtool rrdtool-devel apr-devel
  3. 三个节点依赖Epel

    sh 复制代码
    yum -y install epel-release
  4. 第一个节点上安装Ganglia

    sh 复制代码
    yum -y install ganglia-gmetad ganglia-gmond ganglia-web
  5. 其他两个节点上安装gmond服务

    sh 复制代码
    yum -y install ganglia-gmond
  6. 第一个节点上修改ganglia.conf

    sh 复制代码
    vim /etc/httpd/conf.d/ganglia.conf

    文件修改如下

    sh 复制代码
    <Location /ganglia>
      # Require local
      # Require ip 10.1.2.3
      # Require host example.org
      Require all granted
    </Location>
  7. 第一个节点上修改gmetad.conf

    sh 复制代码
    vim /etc/ganglia/gmetad.conf

    修改data_source属性的值

    sh 复制代码
    data_source "flume_cluster" hadoop01
  8. 三个节点上修改gmond.conf

    sh 复制代码
    vim /etc/ganglia/gmond.conf

    修改cluster中的属性值

    sh 复制代码
    cluster {
      name = "flume_cluster"
      owner = "unspecified"
      latlong = "unspecified"
      url = "unspecified"
    }

    修改udp_send_channel中的属性值

    sh 复制代码
    udp_send_channel {
      #bind_hostname = yes # Highly recommended, soon to be default.
                           # This option tells gmond to use a source address
                           # that resolves to the machine's hostname.  Without
                           # this, the metrics may appear to come from any
                           # interface and the DNS names associated with
                           # those IPs will be used to create the RRDs.
      # mcast_join = 239.2.11.71
      # 将监控的信息发送到指定的节点收集
      host = hadoop01
      port = 8649
      ttl = 1
    }

    修改udp_recv_channel中的属性值

    sh 复制代码
    udp_recv_channel {
      # mcast_join = 239.2.11.71
      port = 8649
      # 接收任意主机的连接
      bind = 0.0.0.0
      retry_bind = true
      # Size of the UDP buffer. If you are handling lots of metrics you really
      # should bump it up to e.g. 10MB or even higher.
      # buffer = 10485760
    }
  9. 三个节点启动gmond服务

    sh 复制代码
    systemctl start gmond
    # 查看进程是否启动
    ps -ef | grep -i gmond
  10. 在一个节点上启动gmetad和httpd服务

    sh 复制代码
    :systemctl start gmetad
    systemctl start httpd
  11. 在浏览器中输入http://IP/ganglia/

监控Flume
  1. 修改Flume的配置

    sh 复制代码
    # 进入Flume的配置目录
    cd /opt/software/flume-1.11.0/conf/
    # 复制文件
    cp flume-env.sh.template flume-env.sh
    # 编辑文件
    vim flume-env.sh
    # 在文件尾部添加
    export JAVA_HOME=/opt/software/jdk1.8
    export JAVA_OPTS="-Dflume.monitoring.type=ganglia -Dflume.root.monitoring.hosts=hadoop01:8649 -Xms100m -Xmx200m"
    # 保存退出,生效
    source flume-env.sh
  2. 启动Flume

    sh 复制代码
    cd ../data
    
    //type =ganglia      type和=之间有空格会报错
    
    //开启监控后,在执行之间的格式文件,就要用这个格式的指令
    flume-ng agent -n a1 -c $FLUME_HOME/conf -f basic.properties -Dflume.root.logger=INFO,console -Dflume.monitoring.type=ganglia -Dflume.monitoring.hosts=hadoop01:8649
  3. 属性解释

    属性 解释
    ChannelCapacity Channel的容量
    ChannelFillPercentage Channel的利用率
    ChannelSize Channel的大小
    EventPutAttemptCount PutList向Channel尝试推送数据的次数
    EventPutSuccessCount PutList向Channel推送数据成功的次数
    EventTakeAttemptCount TakeList向Sink推送数据的次数
    EventTakeSuccessCount TakeList向Sink推送数据成功的次数
    StartTime 起始时间
    StopTime 结束时间
相关推荐
子非鱼92136 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
想退休的搬砖人1 小时前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习1 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css
清汤饺子1 小时前
实践指南之网页转PDF
前端·javascript·react.js
蒟蒻的贤1 小时前
Web APIs 第二天
开发语言·前端·javascript
清灵xmf2 小时前
揭开 Vue 3 中大量使用 ref 的隐藏危机
前端·javascript·vue.js·ref
蘑菇头爱平底锅2 小时前
十万条数据渲染到页面上如何优化
前端·javascript·面试
2301_801074152 小时前
TypeScript异常处理
前端·javascript·typescript