Flume1.9自定义Source和Sink实战

背景

在了解了flume的工作原理之后,在一定程度上可能会有自定义输入源和输出目的地的需求,因此本文做了一个简单的demo,以备后查

自定义Source 

Source是负责接收数据到Flume Agent的组件。Source组件可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy。官方提供的source类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些source

概述 

Flume 1.10.0 Developer Guide — Apache Flume根据官方说明自定义MySource需要继承AbstractSource类并实现Configurable和PollableSource接口。

实现相应方法:

getBackOffSleepIncrement()//暂不用

getMaxBackOffSleepInterval()//暂不用

configure(Context context)//初始化context(读取配置文件内容)

process()//获取数据封装成event并写入channel,这个方法将被循环调用。

使用场景:读取MySQL数据或者其他文件系统

Flume1.9自定义Source和Sink实战_第1张图片  

案例需求 

自定义source,模拟数据源,并给每条数据添加前缀,输出到控制台。前缀可从flume配置文件中配置

编码 

1.创建一个快速maven工程 

 Flume1.9自定义Source和Sink实战_第2张图片

2.增加pom依赖 

PS: 版本最好和客户端版本一直,否则可能出现不兼容的情况

 
        org.apache.flume
        flume-ng-core
        1.9.0
  
package com.flume;

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;

/**
 * 

* 功能描述:自定义的source需要继承以下类,并实现其中的方法 *

* * @author MILLA * @version 1.0 * @since 2022/06/15 10:50 */ public class MyFlumeSource extends AbstractSource implements Configurable, PollableSource { //定义配置文件将来要读取的字段 private Long delay; private String field; /** * @return 接收数据将数据封装成event,写入channel * @throws EventDeliveryException */ @Override public Status process() throws EventDeliveryException { try { //创建事件头信息 HashMap headerMap = new HashMap<>(16); //创建事件 SimpleEvent event = new SimpleEvent(); //循环封装事件 for (int i = 0; i < 5; i++) { //给事件设置头信息 event.setHeaders(headerMap); //给事件设置内容 event.setBody((field + "-" + i).getBytes()); //将事件写入channel getChannelProcessor().processEvent(event); Thread.sleep(delay); } } catch (Exception e) { 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) { delay = context.getLong("delay"); field = context.getString("field", "I am a default value"); } }

 3.打包之后,将生生成的jar拷贝到flume/lib文件下

mvn clean package -DskipTests

 创建flume配置

vi mysource.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = com.flume.MyFlumeSource
a1.sources.r1.delay = 1000
a1.sources.r1.field = customerSource

# Describe the sink
a1.sinks.k1.type = logger

# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

启动任务查看效果 

../../apache-flume-1.9.0-bin/bin/flume-ng agent \
-c ../../apache-flume-1.9.0-bin/conf/ \
-n a1 \
-f mysource.conf -Dflume.root.logger=INFO,console

Flume1.9自定义Source和Sink实战_第3张图片

注释掉mysource.conf中的a1.sources.r1.field = customerSource配置,重新启动效果如下 

Flume1.9自定义Source和Sink实战_第4张图片

 自定义Sink

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

概述 

官方也提供了自定义source的接口:

Flume 1.10.0 Developer Guide — Apache Flume根据官方说明自定义MySink需要继承AbstractSink类并实现Configurable接口。

实现相应方法:

configure(Context context)//初始化context(读取配置文件内容)

process()//从Channel读取获取数据(event),这个方法将被循环调用。

使用场景:读取Channel数据写入MySQL或者其他文件系统

案例需求 

使用flume接收数据,并在Sink端给每条数据添加前缀和后缀,输出到控制台。前后缀可在flume任务配置文件中配置

 编码

在上一个工程上增加自定义Sink代码

package com.flume;

import org.apache.flume.Channel;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.Transaction;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 

* 功能描述:自定义的sink *

* * @author MILLA * @version 1.0 * @since 2022/06/15 11:33 */ public class MyFlumeSink extends AbstractSink implements Configurable { private static final Logger LOG = LoggerFactory.getLogger(AbstractSink.class); private String prefix; private String suffix; @Override public Status process() throws EventDeliveryException { //声明返回值状态信息 Status status; //获取当前Sink绑定的Channel Channel ch = getChannel(); //获取事务 Transaction txn = ch.getTransaction(); //声明事件 Event event; //开启事务 txn.begin(); //读取Channel中的事件,直到读取到事件结束循环 while (true) { event = ch.take(); if (event != null) { break; } } try { //处理事件(打印) LOG.info("Sink输出: " + prefix + new String(event.getBody()) + suffix); //事务提交 txn.commit(); status = Status.READY; } catch (Exception e) { //遇到异常,事务回滚 txn.rollback(); status = Status.BACKOFF; } finally { //关闭事务 txn.close(); } return status; } @Override public void configure(Context context) { //读取配置文件内容,有默认值 prefix = context.getString("prefix", "hello:"); //读取配置文件内容,无默认值 suffix = context.getString("suffix"); } }

创建flume配置 

 vi mysink.conf
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
# 指定自定义的source
a1.sources.r1.type = com.flume.MyFlumeSource
a1.sources.r1.delay = 1000
a1.sources.r1.field = o(∩_∩)o

# Describe the sink
# 指定自定义的sink
a1.sinks.k1.type =com.flume.MyFlumeSink
a1.sinks.k1.prefix = pre-
a1.sinks.k1.suffix = -suf


# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

启动任务 

../../apache-flume-1.9.0-bin/bin/flume-ng agent \
-c ../../apache-flume-1.9.0-bin/conf/ \
-n a1 \
-f mysink.conf -Dflume.root.logger=INFO,console

 执行效果

Flume1.9自定义Source和Sink实战_第5张图片 

 总结

自定义的数据源可以换成从数据库、文件系统、爬虫等等

自定义的输出可以是写入数据库,文件系统等等

同时也将自定义的数据源和自定义的输出整合了起来

 

 

 

你可能感兴趣的:(技术实战,flume,sink)