Flume模拟场景各组件详解

8 篇文章 0 订阅
1 篇文章 0 订阅

由于工作原因,博客没进行更新,不过文章的确写了,就是太懒不想排版,code21.cn可能不会更新了,服务器费用的确太贵
场景模拟
kafka实时json格式数据解析写入hive
了解Flume
Flume中最重要的概念就是agent,数据流向基本依靠这三个组件
在这里插入图片描述
•Source:用来消费(收集)数据源到Channel组件中 数据源
•Channel:中转临时存储,保存所有Source组件信息 数据管道
•Sink:从Channel中读取,读取成功后会删除Channel中的信息 水槽(向目的地发送数据)
官网http://flume.apache.org/FlumeUserGuide.html
在这里插入图片描述
从页面左侧Flume sources channels sinks 可以明显的看出flume支持的源管道,及沉入对象。
上面的业务需求则是要沉入hive,也可以看到flume sinks支持的hive sinks
看了一下官网之前的文档,hivesinks是在flume1.6之后才有的。1.5页面挂了不知道有没有
搜了一下网上关于kafka + flume + hive的 业务逻辑,相关资料比较少
Source
在这个业务中sources采用 kafak source,此项配置比较简单。
Channel
管道先暂时忽略。
Sink
在此业务中最重要的模块就是sink了,官网也有hive sink组件。
下面我们来看一下他的参数
在这里插入图片描述
Hive表结构
在这里插入图片描述
Hive连接设置
Sink类型设置 a1.sinks.k1.type = hive  表示hivesinka1.sinks.k1.hive.metastore = thrift://127.0.0.1:9083a1.sinks.k1.hive.database = logsdba1.sinks.k1.hive.table = weblogsa1.sinks.k1.hive.partition = asia,%{country},%y-%m-%d-%H-%M //分区配置
分区配置与表
partitioned by (continent string, country string, time string)
相对应

字段设置
a1.sinks.k1.serializer = DELIMITEDa1.sinks.k1.serializer.delimiter = "\t"a1.sinks.k1.serializer.serdeSeparator = '\t'a1.sinks.k1.serializer.fieldnames =id,msg
通过 串行化 \t 分割将数据 与fieldnames对应,完成入库

以上是基本的hive sink操作,可以看出配置的确是太简单了。
那么问题来了
我的数据是json数据[{“”:””},{“”:””},{“”:””},{“”:””}]
用普通的分割符貌似解析不出对应的字段,此时引入一个概念,flume 拦截器。
flume 拦截器
Flume过滤器的作用是,将source处的数据进行拦截处理,然后传入管道,在进行sink。
好了,我们来看一下flume的拦截器
在这里插入图片描述
JingxiInterceptor就忽略吧,我自己定义的
从源码中我们可以找到他有八种拦截器
我们对拦截器的大体做一个了解,此处从书上做个截图
在这里插入图片描述
看完是不是发现还是解决不了我们的问题
我的数据是json,没有json拦截器啊
Flume对我们提供了一个接口Interceptor
我们基于这个接口则可以开发拦截器。(自定义拦截器方法在下面)
通过拦截器我们可以得到我们想要的数据格式进行入库操作。
好了,此时我们入库操作已经完成了,但是回到业务上,我们的kafka源是来自不同设备的数据,多数据格式我们需要根据不同的数据入不同的库。
难道我们要开发多套flume agent吗
在这里插入图片描述
此种逻辑完全可以解决业务需求
但是问题来了 拦截器分别在三个不同的agent中
每次都要拦截,相当于一共处理了数据总量乘3的数据
那么这样的资源利用率简直太低了,还不如采用 sparkstreaming 去进行逻辑操作。
Flume又一个概念
Channel选择器
来看一下概念
在这里插入图片描述
此时我们可以通过配合拦截器,就能将不同的数据发到不同的管道进行sink增加了资源利用率

此时的业务逻辑就变成了下图:
在这里插入图片描述
以上的逻辑就完美解决了实际业务需求
同时flume 还有sink组概念,可以同时开启多个节点实现高可用,此处就不介绍了
自定义拦截器
我们看一下flume提供给我们的接口

public interface Interceptor {
  /**
   * Any initialization / startup needed by the Interceptor.
   */
  public void initialize();
  /**
   * Interception of a single {@link Event}.
   * @param event Event to be intercepted
   * @return Original or modified event, or {@code null} if the Event
   * is to be dropped (i.e. filtered out).
   */
  public Event intercept(Event event);
  /**
   * Interception of a batch of {@linkplain Event events}.
   * @param events Input list of events
   * @return Output list of events. The size of output list MUST NOT BE GREATER
   * than the size of the input list (i.e. transformation and removal ONLY).
   * Also, this method MUST NOT return {@code null}. If all events are dropped,
   * then an empty List is returned.
   */
  public List<Event> intercept(List<Event> events);

  /**
   * Perform any closing / shutdown needed by the Interceptor.
   */
  public void close();
  /** Builder implementations MUST have a no-arg constructor */
  public interface Builder extends Configurable {
    public Interceptor build();
  }
}

我们需要实现的方法就是这两个方法

public Event intercept(Event event);
public List<Event> intercept(List<Event> events);

Flume中数据是以事件的形式传递,而且数据结构也非常简单就是包括了 事件头,与事件体,以字节的形式进行传递

下面是我写的拦截器案例

package cn.code21.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.Charsets;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.List;

public class JingxiInterceptor implements Interceptor {
    public void initialize() {
        System.out.println("接收到数据开始拦截过滤··");
    }
    public Event intercept(Event event) {
//        接收到json格式数据开始解析,按照字段名称解析完成返回
        String inputeBody = null;
        String data1 = null;
        byte[] outputBoday = null;
        try {
            inputeBody = new String(event.getBody(), Charsets.UTF_8);
            JSONArray data = JSON.parseArray(inputeBody);
            for (Object item : data) {
                JSONObject itemObj = JSON.parseObject(item.toString());
                String name = itemObj.getString("name");
                String type = itemObj.getString("type");
                String age = itemObj.getString("age");
                data1 = new String(name + "\t" + type + "\t" + age);
            }
            outputBoday = data1.getBytes();

        } catch (Exception e) {
            System.out.println("输入数据" + event);
        }
        event.setBody(outputBoday);
        return event;
    }
    public List<Event> intercept(List<Event> events) {
        for (Event event : events) {
            intercept(event);
        }
        return events;
    }
    public void close() {
        System.out.println("过滤完成");
    }

    public static class Builder implements Interceptor.Builder {
        public Interceptor build() {
            return new JingxiInterceptor();
        }
        public void configure(Context context) {
            // 此处可以获取conf中的参数
        }
    }

}

代码就不多做介绍了,需要注意的是,如果拦截器能够运行还需要实现一个接口Interceptor.Builder,作为入口
编写完程序就可以进行打包了(注意如果使用第三方依赖,打包的时候一定要将依赖一起打入)
将自己的拦截器 放入flume/lib 目录下,进行conf配置启动flume
效果图:
在这里插入图片描述
可以看到只有符合拦截器格式的数据才进行输出,此时就完全可以使用了。
资料参考
Flume官网http://flume.apache.org/FlumeUserGuide.html
《Flume 构建高可用、可扩展的海量日志采集系统》
在这里插入图片描述
附加
flume目前还是由于很多公司在使用作为公司的日志收集组件,但是由于flume是运行与JVM的,以及吞吐量并不是很理想,可能会有更优秀的组件来替代flume,这就需要自己来调研了
在这里插入图片描述
欢迎扫码进群,期待更优秀的你!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值