目录
定义 CustomInterceptor 类并实现 Interceptor 接口。
分别在 hadoop12,hadoop13,hadoop14 上启动 flume 进程,注意先后顺序。
在 hadoop12 使用 netcat 向 localhost:44444 发送字母和数字。
自定义 Interceptor
1)案例需求
使用 Flume 采集服务器本地日志,需要按照日志类型的不同,将不同种类的日志发往不同的分析系统。
2)需求分析
在实际的开发中,一台服务器产生的日志类型可能有很多种,不同类型的日志可能需要发送到不同的分析系统。此时会用到 Flume 拓扑结构中的 Multiplexing 结构,Multiplexing 的原理是,根据 event 中 Header 的某个 key 的值,将不同的 event 发送到不同的 Channel 中。所以我们需要自定义一个 Interceptor,为不同类型的 event 的 Header 中的 key 赋予不同的值。
在该案例中,我们以端口数据模拟日志,以是否包含“lzl”模拟不同类型的日志,我们需要自定义 interceptor 区分数据中是否包含“lzl”,将其分别发往不同的分析系统(Channel)。
3)实现步骤
-
创建一个 Maven 项目,并引入以下依赖。
<dependency> <groupId>org.apache.flume</groupId> <artifactId>flume-ng-core</artifactId> <version>1.9.0</version> </dependency>
-
定义 CustomInterceptor 类并实现 Interceptor 接口。
package com.lzl.interceptor; 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 TypeInterceptor 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()); // 3. 根据 body 中是否有"lzl"来决定添加怎样的头信息 if (body.contains("lzl")) { // 4. 添加头信息 headers.put("type", "first"); } else { // 4. 添加头信息 headers.put("type", "second"); } return event; } // 批量事件拦截 @Override public List<Event> intercept(List<Event> events) { // 1. 清空集合 addHeaderEvents.clear(); // 2. 遍历 events for (Event event : events) { // 3. 给每一个事件添加头信息 addHeaderEvents.add(intercept(event)); } // 4. 返回结果 return addHeaderEvents; } @Override public void close() { } public static class Builder implements Interceptor.Builder { @Override public Interceptor build() { return new TypeInterceptor(); } @Override public void configure(Context context) { } } }
-
编辑 flume 配置文件
为
hadoop12
上的Flume1
配置 1 个netcat source
,1 个sink group
(2 个avro sink
),并配置相应的ChannelSelector
和interceptor
。# Name the components on this agent a1.sources = r1 a1.sinks = k1 k2 a1.channels = c1 c2 # Describe/configure the source a1.sources.r1.type = netcat a1.sources.r1.bind = localhost a1.sources.r1.port = 44444 a1.sources.r1.interceptors = i1 a1.sources.r1.interceptors.i1.type = com.lzl.flume.interceptor.TypeInterceptor$Builder a1.sources.r1.selector.type = multiplexing a1.sources.r1.selector.header = type a1.sources.r1.selector.mapping.first = c1 a1.sources.r1.selector.mapping.second = c2 # Describe the sink a1.sinks.k1.type = avro a1.sinks.k1.hostname = hadoop13 a1.sinks.k1.port = 4141 a1.sinks.k2.type=avro a1.sinks.k2.hostname = hadoop14 a1.sinks.k2.port = 4242 # Use a channel which buffers events in memory a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # Use a channel which buffers events in memory a1.channels.c2.type = memory a1.channels.c2.capacity = 1000 a1.channels.c2.transactionCapacity = 100 # Bind the source and sink to the channel a1.sources.r1.channels = c1 c2 a1.sinks.k1.channel = c1 a1.sinks.k2.channel = c2
为
hadoop13
上的Flume4
配置一个avro source
和一个logger sink
。a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sources.r1.type = avro a1.sources.r1.bind = hadoop13 a1.sources.r1.port = 4141 a1.sinks.k1.type = logger a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 a1.sinks.k1.channel = c1 a1.sources.r1.channels = c1
为
hadoop14
上的Flume3
配置一个avro source
和一个logger sink
。a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sources.r1.type = avro a1.sources.r1.bind = hadoop14 a1.sources.r1.port = 4242 a1.sinks.k1.type = logger a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 a1.sinks.k1.channel = c1 a1.sources.r1.channels = c1
-
分别在 hadoop12,hadoop13,hadoop14 上启动 flume 进程,注意先后顺序。
-
在 hadoop12 使用 netcat 向 localhost:44444 发送字母和数字。
-
观察 hadoop13 和 hadoop14 打印的日志。