flume配置
详解:从一个logfile日志读取,然后在channel端添加拦截器,选择器发往不同的topic主题 从而实现事件的区分
a1.sources = r1
a1.channels = c1 c2
a1.sources.r1.type = TAILDIR
a1.sources.r1.positionFile = /var/log/flume/taildir_position.json
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /var/log/test1/example.log //监控一个目录 后面用拦截器将body的字段放入到header中,然后用选择器选择对应的header将其发往不同的topic主题
a1.sources.r1.fileHeader = true
a1.sources.r1.channels = c1 c2
#interceptor
a1.sources.r1.interceptors = i1 i2//这里的俩个拦截器分别发往不同的Topic的channel c1 和 c1
a1.sources.r1.interceptors.i1.type = org.apache.flume.interceptor.MyInterceptor$Builder//这里是咱自定义的拦截器,就是将body中的内容放入到header中
a1.sources.r1.interceptors.i2.type = org.apache.flume.sink.solr.morphline.UUIDInterceptor$Builder //uuid拦截器 用来均匀的发往kafka中的分区
#selector
a1.sources.r1.selector.type = multiplexing//replicating和multiplexing的区别是replicating会将所有的事件复制到所有的channel端,而multiplexing依据指定的header值,将event路由至不同的channel,依据是检查header中的键值对与mapping中的配置的值是否是一致的。
a1.sources.r1.selector.header = topic//这里的header对应代码里的头部,从头部里进行选择,这里是KEY
a1.sources.r1.selector.mapping.topic_start = c1//发往c1的channel,这里是VALUE
a1.sources.r1.selector.mapping.topic_event = c2//发往c2的channel,这里是VALUE
#kafkachannel
a1.channels.c1.type = org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers = kafka-1:9092,kafka-2:9092,kafka-3:9092
a1.channels.c1.kafka.topic = topic_start //当header中存在topic_start的话则发往此topic
a1.channels.c1.kafka.consumer.group.id = flume-consumer
a1.channels.c2.type = org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c2.kafka.bootstrap.servers = kafka-1:9092,kafka-2:9092,kafka-3:9092
a1.channels.c2.kafka.topic = topic_event
a1.channels.c2.kafka.consumer.group.id = flume-consumer
package flumeDemo;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MyInterceptor implements Interceptor {
@Override
public void initialize() {
//只需要实现处理出来 不需要写具体的方法
}
@Override//具体的逻辑
public Event intercept(Event event) {
//1.从body里面拿到数据,后面做关键字判断
byte[] body = event.getBody();
//将事件类型转换为UTF-8,我猜测这里应该是avro序列化所以无法直接识别
String log = new String(body, Charset.forName("UTF-8"));
//2.获取header
Map<String, String> headers = event.getHeaders();
//2.(json) 事件日志
if (log.contains("start")) {
//将topic 和topic_start放入头部,以kv键值对的方式,通过选择器发往不同的topic主题
headers.put("topic", "topic_start");//a1.sources.r1.selector.mapping.topic_start=c1
} else {
headers.put("topic", "topic_event");//a1.sources.r1.selector.mapping.topic_event=c2
}
return event;
}
@Override//都是套路
public List<Event> intercept(List<Event> events) {
//多条事件处理
ArrayList<Event> interceptors=new ArrayList<>();
for(Event en:events){
Event intercept = intercept(en);
if(intercept!=null)//判断事件不为null
{
interceptors.add(intercept);
}
}
return interceptors;
}
@Override
public void close() {
//只需要实现处理出来 不需要写具体的方法
}
public static class Builder implements Interceptor.Builder{
//实现builder方法,在配置中没有机会修改
@Override
public Interceptor build() {
return new MyInterceptor();
}
@Override
public void configure(Context context) {
//只需要实现处理出来 不需要写具体的方法
}
}
}