flume筆記(四)之 自定義攔截器-Interceptor

一.案例概述

  首先flume在實際開發中的日誌處理的要去各不相同,然而官方所給的案例不能滿足我實際開發者的要求,所以就有了自定義Interceptor這個概念。它需要按照日誌類型的不同,將不同種類的日誌發往不同的分析系統。
  而下面的一個小案例我採用的的拓撲結構是Multiplexing 結構。這個前面的文章中也提到過。其原理是根據event 中 Header 的某個 key 的值,將不同的 event 發送到不同的 Channel中,所以我們需要自定義一個 Interceptor,爲不同類型的 event 的 Header 中的 key 賦予不同的值。
  我門閒話少說直接上案例,該案例使用自定義攔截器將是否包含hello信息發送給不同分析系統。

二.實現步驟

1.創建一個maven 項目,並引入以下依賴。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>
    <dependency>
        <groupId>org.apache.flume</groupId>
        <artifactId>flume-ng-core</artifactId>
        <version>1.7.0</version>
    </dependency>
</dependencies>

2.定義 TestInterceptor類並實現 Interceptor 接口。然後將其打包將jar放入虛擬機中flume安裝目錄的lib文件夾。

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class TestInterceptor implements Interceptor{
    //聲明一個存放事件的集合
    private List<Event> addHeaderEvents;

    //初始化
    @Override
    public void initialize() {
        //初始化
        addHeaderEvents = new ArrayList<>();
    }

    //單個事件攔截
    @Override
    public Event intercept(Event event) {
        //1.獲取事件中的頭信息
        Map<String, String> headers = event.getHeaders();
        //2.獲取事件中的body信息
        String body = new String(event.getBody());   //因爲getBody爲字節流byte[]
        //3.根據body中是否有“hello”來決定添加怎樣的信息
        if (body.contains("hello")){
            //添加頭部信息
            headers.put("type","Hello");
        }else {
            //添加頭部信息
            headers.put("type","NoHello");
        }
        return event;
    }

    //批量事件攔截
    @Override
    public List<Event> intercept(List<Event> list) {
        //1.清空集合
        addHeaderEvents.clear();
        //2.遍歷events
        for (Event event:list) {
            addHeaderEvents.add(intercept(event));
        }
        //3.返回結果
        return addHeaderEvents;
    }

    @Override
    public void close() {
    }

    public static class Builder implements Interceptor.Builder{
        @Override
        public Interceptor build() {
            return new TestInterceptor();
        }

        @Override
        public void configure(Context context) {
        }
    }
}

3.在hadoop-1上編輯flume-netcat-flume.conf 配置文件。配置1個netcat source,2個avro sink和相應的ChannelSelector 和 interceptor。

# name
a1.sources = r1
a1.channels = c1 c2 
a1.sinks = k1 k2 

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

# interceptors
a1.sources.r1.interceptors = i1
# TestInterceptor自定義攔截器的全類名 和  Builder靜態內部類的名稱
a1.sources.r1.interceptors.i1.type = TestInterceptor$Builder

# channel  selector
a1.sources.r1.selector.type = multiplexing
# 注意 該值要和自定義攔截器中設置的 header 一致,我設置的是type
a1.sources.r1.selector.header = type
# 這裏也是同理  官方給的是a1.sources.r1.selector.mapping.CZ 而我設置的爲 Hello
a1.sources.r1.selector.mapping.Hello = c1
# 官方給的是a1.sources.r1.selector.mapping.US 而我設置的爲 NoHello
a1.sources.r1.selector.mapping.NoHello = c2

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

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

# Sink
a1.sink.k1.type = avro 
a1.sink.k1.hostname = hadoop-2
a1.sink.k1.port = 4142

a1.sink.k2.type = avro 
a1.sink.k2.hostname = hadoop-3
a1.sink.k2.port = 4142

# bind 
a1.sources.r1.channels = c1 c2 
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2

4.在hadoop-2上編輯flume-flume-console1.conf,配置一個 avro source 和一個 logger sink。

#name
a2.sources = r1
a2.channels = c1
a2.sinks = k1 

#Source
a2.sources.r1.type = avro
a2.sources.r1.bind = hadoop-2
a2.sources.r1.port = 4142

#Channel
a2.channels.c1.type = memory
a2.channels.c1.capacity = 1000
a2.channels.c1.transactionCapacity = 100

#Sink
# 輸出到控制檯
a2.sinks.k1.type = logger

#Bind
a2.sources.r1.channels = c1
a2.sinks.k1.channel = c1

5.在hadoop-3上編輯flume-flume-console2.conf,配置一個 avro source 和一個 logger sink。

#name
a3.sources = r1
a3.channels = c1
a3.sinks = k1 

#Source
a3.sources.r1.type = avro
a3.sources.r1.bind = hadoop-3
a3.sources.r1.port = 4142

#Channel
a3.channels.c1.type = memory
a3.channels.c1.capacity = 1000
a3.channels.c1.transactionCapacity = 100

#Sink
# 輸出到控制檯
a3.sinks.k1.type = logger

#Bind
a3.sources.r1.channels = c1
a3.sinks.k1.channel = c1

6.先啓動hadoop-2 和 hadoop-3的flume配置文件,最後啓動hadoop-1的flume配置文件。
7.在hadoop-1上測試 使用netcat端口 向localhost:44444 發送信息。
8. 打印結果:如果發送的信息包含hello則在打印在hadoop-2上,否則打印在hadoop-3上。
總結:自定義攔截器在實際開發中用處還是非常大的,它可以完成各種數據處理的邏輯。

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