自定义flume的sink
目标:自定义sink,将rocketmq中的数据落地到本地文件
source的process方法相当于Event的生产者,不断向Channel中发送Event
sink的process方法相当于Event的消费者,不断从Channel中取出Event进行处理
总体流程:
1、通过getChannel方法 获取channel对象;
Channel ch = getChannel(); //获取当前sink绑定的channel
2、通过take方法从channel中取出Event
event = ch.take(); //取出消息Event
3、通过getBody获取消息的详细内容
byte[] msg = event.getBody(); //获取消息的详细内容
4、保存到本地,或者保存到HDFS
模版
public class MySink extends AbstractSink implements Configurable {
// 创建 Logger 对象
private static final Logger logger = LoggerFactory.getLogger(AbstractSink.class);
private String prefix;
private String suffix;
@Override
public void configure(Context context) {
// 读取配置文件内容,有默认值
prefix = context.getString("prefix", "hello:");
// 读取配置文件内容,无默认值
suffix = context.getString("suffix");
}
/**
* 1.获取 Channel
* 2.从 Channel 获取事务和数据
* 3.发送数据
*/
@Override
public Status process() throws EventDeliveryException {
// 声明返回值状态信息
Status status;
// 获取当前 Sink 绑定的 Channel
Channel ch = getChannel();
// 获取事务
Transaction txn = ch.getTransaction();
// 声明事件
Event event;
// 开启事务
txn.begin();
// 读取 Channel 中的事件,直到读取到事件结束循环
while (true) {
event = ch.take();
if (event != null) {
break;
}
}
try {
// 处理事件(打印)
logger.info(prefix + new String(event.getBody()) + suffix);
// 事务提交
txn.commit();
status = Status.READY;
} catch (Exception e) {
// 遇到异常,事务回滚
txn.rollback();
status = Status.BACKOFF;
} finally {
// 关闭事务
txn.close();
}
return status;
}
@Override
public void start() {
// Initialize the connection to the external repository (e.g. HDFS) that this Sink will forward Events to ..
// 初始化与外部存储库(例如HDFS)的连接,此接收器会将事件转发到。
}
@Override
public void stop () {
// Disconnect from the external respository and do any additional cleanup (e.g. releasing resources or nulling-out field values) ..
// 断开与外部存储库的连接,然后进行其他任何清理操作(例如,释放资源或清空字段值)。
}
}
详细解读:
核心:两个方法:
1、configure 获取配置信息
@Override
public void configure(Context context) {}
2、process 核心处理
关键的几个点:
(1)getChannel方法(在父类AbstractSink中实现)
取得当前sink绑定的channel对象,即拿到了要获取数据的channel
public synchronized Channel getChannel() { return this.channel; }
(2) Channel接口提供了对事务进行操作的两个方法:
@Public @Stable public interface Channel extends LifecycleAware, NamedComponent { void put(Event var1) throws ChannelException; Event take() throws ChannelException; Transaction getTransaction(); }
getTransaction 获取事务
取得事务对象,保证该数据被自定义的sink成功消费,消费成功,就进行事务提交,commit;同时Event将会从channel队列中删除;
如果没有成功消费,那么使用
txn.rollback();//遇到异常,事务回滚
进行事务回滚,该Event仍然保留在channel队列里,等待下一次消费,保证消息不丢失。
take 取出消息Event (事件)
然后获取消息的详细内容 getBody 方法
byte[] mssage = event.getBody(); //获取消息的详细内容
接下来就可以进行消息保存到本地文件,或者传入到HDFS等。
@Override
public Status process() throws EventDeliveryException {
Channel ch = getChannel(); //获取当前sink绑定的channel
//get the transaction 获取事务
Transaction txn = ch.getTransaction();
try {
//begin the transaction
txn.begin();
Event event = null; //声明事件
//读取channel中的事件,直到读取到事件结束循环
while (true) {
event = ch.take(); //取出消息Event
if (event != null) break;
}
byte[] msg = event.getBody(); //获取消息的详细内容
//保存到本地文件
txn.commit();//提交事务
return Status.READY;
} catch (Throwable th) {
txn.rollback();//遇到异常,事务回滚
if (th instanceof Error) throw (Error) th;
else throw new EventDeliveryException(th);
} finally {
txn.close();//关闭事务
} catch (Exception e) {
e.printStackTrace();
}
}
自定义sink需要继承 AbstractSink类,然后实现 Configurable接口
public interface Configurable {
void configure(Context var1);
}
主要是实现接口中的
void configure(Context var1);
方法。
作用是:获取配置信息。
Context类提供了很多获取配置信息的方法
getBoolean
getInteger
getDouble
getString
getFloat
等等。