简介
概述
基本概念
流动模型
-
单级流动
-
多级流动
-
扇入流动
-
扇出流动
入门
3. 编写格式文件
在data目录下创建一个文件,文件名,文件后缀随意
#给agent,source起名
a1.sources=s1
#给channel起名
a1.channels=c1
#给sink起名
a1.sinks=k1
#配置Source
a1.sources.s1.type=netcat //表示监听tcp请求,把tcp请求的内容作为日志数据
a1.sources.s1.bind=0.0.0.0 //配置监听的节点ip
a1.sources.s1.port=8090 //配置监听的端口
#配置Channel
a1.channels.c1.type=memory //表示临时把数据存储到内存中
a1.channels.c1.capacity=10000 //表示允许临时在内存中存储一万条数据
a1.channels.c1.transactionCapacity=100 //表示事务容量
#配置sink
a1.sinks.k1.type=logger //表示把数据打印到控制台上
#将Source和Channel进行绑定
a1.sources.s1.channels=c1
#将Sink和Channel进行绑定
a1.sinks.k1.channel=c1
执行启动命令:
…/bin/flume-ng agent -n a1 -c …/conf -f basic.conf -Dflume.root.logger=INFO,console
新开窗口,执行命令
nc hadoop01 8090 //nc表示向 hadoop01的8090端口发送一个tcp请求
组件
一.Source
1.AVRO Source
#编辑格式文件,先进到这个目录下
/home/software/apache-flume-1.7.0-bin/data
vim avrosource.conf
a1.sources=s1
a1.channels=c1
a1.sinks=k1
a1.sources.s1.type=avro
a1.sources.s1.bind=0.0.0.0
a1.sources.s1.port=8090
a1.channels.c1.type=memory
a1.sinks.k1.type=logger
a1.sources.s1.channels=c1
a1.sinks.k1.channel=c1
#指定启动命令
…/bin/flume-ng agent -n a1 -c …/conf -f avrosource.conf -Dflume.root.logger=INFO,console
#发送AVRO序列化之后的数据
#新开一个窗口
cd /home/software/apache-flume-1.7.0-bin/data
vim avrotest #在这个文件中添加内容
#序列化文件并发送
…/bin/flume-ng avro-client -H hadoop01 -p 8090 -c …/conf -F avrotest
Exec Source
Spooling Directory Source
HTTP Source
自定义source
- 需求:模拟:Sequence Generator Source
package cn.tedu.flume.source;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.EventDrivenSource;
import org.apache.flume.channel.ChannelProcessor;
import org.apache.flume.conf.Configurable;
import org.apache.flume.event.EventBuilder;
import org.apache.flume.source.AbstractSource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// 模拟:Sequence Generator Source
public class AuthSource extends AbstractSource
implements EventDrivenSource, Configurable {
private ExecutorService es;
private int step;
// 获取指定的属性的值
@Override
public void configure(Context context) {
// 如果指定了step的值,那么就按照指定的步长来自增
// 如果没有指定step,那么默认自增步长为1
//这里实际上是获得配置文件中a1.sources.s1.step的属性值,
//后续根据指定的第一个参数的字符串内容不同,可以获取不同的属性值,后边的1
//表示,如果不指定的默认值
step = context.getInteger("step", 1);
}
@Override
public synchronized void start() {
es = Executors.newFixedThreadPool(5);
// 获取Channel
ChannelProcessor cp = this.getChannelProcessor();
es.submit(new Add(step, cp));
}
@Override
public synchronized void stop() {
if (es != null) {
es.shutdown();
}
}
}
class Add implements Runnable {
private final int step;
private final ChannelProcessor cp;
public Add(int step, ChannelProcessor cp) {
this.step = step;
this.cp = cp;
}
@Override
public void run() {
int i = 0;
while (true) {
// 封装headers
Map<String, String> headers = new HashMap<>();
headers.put("date", System.currentTimeMillis() + "");
// 封装body
byte[] body = (i + "").getBytes();
// 在Flume中,会将收集到的每一条日志封装成一个Event对象
Event e = EventBuilder.withBody(body, headers);
// 将Event对象放到Channel中
cp.processEvent(e);
i += step;
}
}
}
将项目进行打包,将jar包放到/home/software/apache-flume-1.7.0-bin/lib目录下
然后格式化配置文件auth.conf
a1.sources=s1
a1.channels=c1
a1.sinks=k1
a1.sources.s1.type=cn.tedu.flume.source.AuthSource #注意这里要写成类的全路径名
a1.sources.s1.port=8090
a1.channels.c1.type=memory
a1.sinks.k1.type=logger
a1.sources.s1.channels=c1
a1.sinks.k1.channel=c1
然后使用这个配置文件启动自定义source即可
Channel
- Memory Channel
- File Channel
Sink
- HDFS Sink
- Logger Sink
- File Roll Sink
- AVRO Sink(实现多级流动、扇入流动和扇出流动)
多级流动
扇入流动
删除流动
自定义sink
Custom Sink:需要自定义一个类实现Sink接口,在实现过程中,需要注意事务。
案例: 将数据写出到指定路径下
package cn.tedu.flume.sink;
import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import java.io.PrintStream;
import java.util.Map;
// 将数据写出到指定路径下
public class AuthSink extends AbstractSink implements Sink, Configurable {
private String path;
private PrintStream ps;
@Override
public void configure(Context context) {
// 获取指定的路径
String path = context.getString("path");
if (path == null)
throw new IllegalArgumentException("必须定义path属性!!!");
this.path = path;
}
@Override
public synchronized void start() {
try {
ps = new PrintStream(path + "/" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Status process() {
// 获取Channel
Channel c = this.getChannel();
// 获取事务
Transaction t = c.getTransaction();
// 开启事务
t.begin();
// 从Channel中获取数据
Event e;
try {
while ((e = c.take()) != null) {
// 获取headers
Map<String, String> headers = e.getHeaders();
// 写出headers
ps.println("headers:");
for (Map.Entry<String, String> entry : headers.entrySet()) {
ps.println("\t" + entry.getKey() + "=" + entry.getValue());
}
// 获取body
byte[] body = e.getBody();
// 写出body
ps.println("body:");
ps.println(new String(body));
}
// 事务提交
t.commit();
return Status.READY;
} catch (Exception ex) {
// 事务回滚
t.rollback();
return Status.BACKOFF;
} finally {
// 关闭事务
t.close();
}
}
@Override
public synchronized void stop() {
if (ps != null) {
ps.close();
}
}
}
将项目打包放到cd /home/software/apache-flume-1.7.0-bin/lib目录下。
然后在cd /home/software/apache-flume-1.7.0-bin/data目录下创建conf文件,内容如下,注意类的全路径和要写到的文件路径。
Selector
Processor
data中的conf文件(因为这是在扇出的基础上来玩的),所以第一个系节点在扇出的基础上添加如下配置信息,其他的都是用扇出结构的配置即可:
图文描述
还可以用在sink输出到hdfs的场景,实现按天存放文件,配置如下:
Interceptor
多个拦截器链配置
search and Replace拦截器配置
Regex Filtering拦截器配置