三十九、Flume自定義Source、Sink

上篇文章咱們基於Flume舉了幾個例子,包括它的扇入扇出等等。這篇文章我們主要來看一下怎樣通過自定義Source和Sink來實現Flume的數據採集。關注專欄《破繭成蝶——大數據篇》,查看更多相關的內容~


目錄

一、自定義Source

1.1 需求說明

1.2 編碼實現

1.3 編寫Flume配置文件

1.4 測試自定義的Source

二、自定義Sink

2.1 需求說明

2.2 代碼實現

2.3 編寫Flume的配置文件

2.4 測試自定義Sink


一、自定義Source

Source是負責接收數據到Flume Agent的組件,我們不僅可以根據Flume自身提供的API,實現Source的定義,還可以根據項目的實際需求,編寫自己的Source,比如Source可以是從網絡上下載一個文件,或者是從數據庫中查詢到的數據。Source組件可以處理各種類型、各種格式的日誌數據,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy等等。官方提供的source類型已經很多,但是有時候並不能滿足實際開發當中的需求,此時我們就需要根據實際需求自定義某些Source。

自定義的Source有兩種類型:PollableSource(輪訓拉取)與EventDrivenSource (事件驅動)。兩者的區別在於PollableSource是通過線程不斷去調用process方法,主動拉取消息,而EventDrivenSource是需要觸發一個調用機制,即被動等待。在利用PollableSource實現自定義Source時還需要實現Configurable接口,以便在項目中初始化某些配置。下面我們就以實現PollableSource爲例進行自定義Source的說明。官方也提供了自定義source的接口,可以點擊這裏進行查看~

1.1 需求說明

使用Flume接收數據,自定義Source接收數據,並將數據輸出到控制檯。

1.2 編碼實現

首先需要導入Maven依賴,如下所示:

        <dependency>
            <groupId>org.apache.flume</groupId>
            <artifactId>flume-ng-core</artifactId>
            <version>1.7.0</version>
        </dependency>

實現自定義Source的代碼如下所示:

package com.xzw.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;
import java.util.Map;

/**
 * @author: xzw
 * @create_date: 2021/1/14 15:24
 * @desc: 自定義source
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class MySource extends AbstractSource implements Configurable, PollableSource {

    //定義需要從配置中讀取的字段

    //兩條數據之間的間隔
    private long delay;
    //模擬信息
    private String field;

    /**
     * 處理過程
     *
     * @return
     * @throws EventDeliveryException
     */
    public Status process() throws EventDeliveryException {
        try {
            Map<String, String> header = new HashMap<>();
            SimpleEvent event = new SimpleEvent();
            //拿到數據
            for (int i = 0; i < 5; i++) {
                event.setHeaders(header);
                event.setBody((field + i).getBytes());
                getChannelProcessor().processEvent(event);
                Thread.sleep(delay);
            }
        } catch (Exception e) {
            return Status.BACKOFF;
        }

        return Status.READY;
    }

    /**
     * 回滾之後睡眠增加多長時間(每回滾一次增加多長時間)
     *
     * @return
     */
    public long getBackOffSleepIncrement() {
        return 0;
    }

    /**
     * 最大的失敗睡眠間隔
     *
     * @return
     */
    public long getMaxBackOffSleepInterval() {
        return 0;
    }

    /**
     * 配置方法
     *
     * @param context
     */
    public void configure(Context context) {
        delay = context.getLong("delay", 2000l);
        field = context.getString("field", "xzw");
    }

    public static void main(String[] args) {

    }
}

1.3 編寫Flume配置文件

自定義flume-mysource.conf配置文件並添加如下內容:

a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = com.xzw.source.MySource
a1.sources.r1.delay = 5000
#a1.sources.r1.field = xzw

a1.sinks.k1.type = logger

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

1.4 測試自定義的Source

將寫好的代碼打包上傳到Flume的lib目錄下,我們這裏的路徑是/opt/modules/flume/lib。使用如下命令啓動Flume進行測試:

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

可以發現在控制天打印出了我們傳輸的數據:

二、自定義Sink

Sink組件目的地包括hdfs、logger、avro、thrift、ipc、file、null、HBase、solr等等,但是有時候並不能滿足實際開發當中的需求,此時我們就需要根據實際需求自定義某些Sink。官方也提供了自定義source的接口,請點擊這裏進行查看~

2.1 需求說明

使用Flume接收數據,並在Sink端給每條數據添加前綴和後綴,最後將添加了後綴的數據輸出到控制檯。

2.2 代碼實現

實現自定義Sink的代碼如下所示:

package com.xzw.source;

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

/**
 * @author: xzw
 * @create_date: 2021/1/15 10:09
 * @desc: 自定義sink
 * @modifier:
 * @modified_date:
 * @desc:
 */
public class MySink extends AbstractSink implements Configurable {

    //創建Logger對象
    private static final Logger LOG = LoggerFactory.getLogger(AbstractSink.class);

    //聲明前綴和後綴
    private String prefix = "";
    private String suffix = "";

    @Override
    public Status process() throws EventDeliveryException {
        //聲明返回值狀態信息
        Status status = null;

        //獲取當前sink綁定的channel
        Channel channel = getChannel();

        //獲取事務
        Transaction transaction = channel.getTransaction();

        //開啓事務
        transaction.begin();

        try {
            //聲明事件
            Event take;
            while ((take = channel.take()) == null) {
                Thread.sleep(200);
            }

            //處理事件
            LOG.info(prefix + new String(take.getBody()) + suffix);

            //事務提交
            transaction.commit();
            status = Status.READY;
        } catch (Throwable e) {
            //當遇到異常的時候,回滾事務
            transaction.rollback();
            status = Status.BACKOFF;

            if (e instanceof Error) {
                throw (Error) e;
            }
        } finally {
            //關閉事務
            transaction.close();
        }

        return status;
    }

    @Override
    public void configure(Context context) {
        //讀取配置文件內容,有默認值
        prefix = context.getString("prefix", "PREFIX:");
        //讀取配置文件內容,沒有默認值
        suffix = context.getString("suffix");

    }

    public static void main(String[] args) {

    }
}

2.3 編寫Flume的配置文件

編寫flume-mysink.conf配置文件,文件內容如下所示:

a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444

a1.sinks.k1.type = com.xzw.source.MySink
a1.sinks.k1.suffix = :SUFFIX

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

2.4 測試自定義Sink

將編寫好的代碼打包上傳到Flume的lib目錄下,使用如下命令啓動Flume:

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

通過測試可以發現,數據通過自定義的Sink輸出到控制檯:

 

OK,本文就介紹到這裏,自定義的Source、Sink這部分比較簡單,你們在這個過程中遇到了什麼問題,歡迎留言,讓我看看你們遇到了什麼問題~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章