一.案例概述
首先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上。
总结:自定义拦截器在实际开发中用处还是非常大的,它可以完成各种数据处理的逻辑。