flume 自定义 hbase sink
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flume 自定义 hbase sink相关的知识,希望对你有一定的参考价值。
参考技术A 业务需求 flume需要从kafka获取数据并写入hbase
开始写的想法:按照flume的流程:一个source ,三个channel, 三个sink,因为我需要三个列族,如果使用官方的hbase sink那么需要三个sink。而且需要自定义一个source的拦截器,根据kafka获取的数据匹配不不同的channel,三个channel对应三个列族,然后配置到sink,就可以使用官方hbase的sink插入数据了。
实现:
1. 自定义一个拦截器
自定义拦截器
将自定义拦截器打成jar包,放到flume的lib目录,有依赖的包也需要将jar包一并放入,不然会报找不到包异常
conf/flume-diysource.conf 配置信息
一切准备就绪flume启动命令
控制台打印信息没报什么错误
查看hbase,hbase的列族是分对了,但是他把整一个kafka读取的数据当做一个value写入一列,而且列名是默认的,并不是我想要的。
于是..............diy开始了
当我在看flume的时候看到关于kafka channel是 这样写的
思路:根据 3 我们可以不需要再写一个source,直接channel 到 sink 一撸到底,只需要在sink上进行habse的相关操作
直接自定义 sink
依赖信息
自定义类 MyHbaseSink
自定义完毕,开始配置文件 ,这个配置就比较简单 conf/flume-diysource.conf 文件
一切准备好了,将自定义的sink打成jar包,放到flume,直接运行
后台运行
完美运行,habse在哗啦啦的写入!
总结: 业务需求是将kafka的数据写入到hbase,开始是想用官方的sink,结果是我太天真了,官方的hbase sink的rowKey并不满足业务需求,而且kafka的数据字段是不确定的,搞了半天,白忙活。发现自己定义的比较符合业务需求。
但是,自定义的sink也是比较坑的,开始自定sink,我把处理event的逻辑全都放在process() 方法里,结果很抽风,根本就没有执行到我的逻辑里,然后我在官网process()方法的上看到这么一句话: Send the Event to the external repository.
大概意思是让我把event发送到外部库,于是我把event处理独立出process()。结果amazing,成功写入hbase了,果然运气不错!
Flume-自定义 Sink
Sink 不断地轮询 Channel 中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个 Flume Agent。
Sink 是完全事务性的。
在从 Channel 批量删除数据之前,每个 Sink 用 Channel 启动一个事务。
批量事件一旦成功写出到存储系统或下一个 Flume Agent,Sink 就利用 Channel 提交事务。
事务一旦被提交,该 Channel 从自己的内部缓冲区删除事件。
Sink 组件目的地包括 hdfs、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。官方提供的 Sink 类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些 Sink。
官方也提供了自定义 sink 的接口:https://flume.apache.org/FlumeDeveloperGuide.html#sink
根据官方说明自定义 Sink 需要继承 AbstractSink 类并实现 Configurable 接口。
实现相应方法:
// 初始化 context(读取配置文件内容) configure(Context context); // 从 Channel 读取获取数据(event),这个方法将被循环调用 process();
使用场景:读取 Channel 数据写入 MySQL 或者其他文件系统。
使用 flume 接收数据,并在 Sink 端给每条数据添加前缀和后缀,输出到控制台。前后缀可在 flume 任务配置文件中配置。
一、创建自定义 Sink
1.添加 pom 依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>flume</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.apache.flume</groupId> <artifactId>flume-ng-core</artifactId> <version>1.9.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
2.编写自定义的 Sink 类
package sink; import org.apache.flume.*; import org.apache.flume.conf.Configurable; import org.apache.flume.sink.AbstractSink; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MySink extends AbstractSink implements Configurable { // 创建 Logger 对象 private static final Logger LOG = LoggerFactory.getLogger(AbstractSink.class); private String prefix; private String 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 { // 处理事件(打印) LOG.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 configure(Context context) { // 读取配置文件内容,有默认值 prefix = context.getString("prefix", "hello:"); // 读取配置文件内容,无默认值 suffix = context.getString("suffix"); } @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.打包上传
参考:https://www.cnblogs.com/jhxxb/p/11582804.html
2.编写 flume 配置文件
mysink.conf
# Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = netcat a1.sources.r1.bind = 127.0.0.1 a1.sources.r1.port = 4444 # Describe the sink a1.sinks.k1.type = sink.MySink # a1.sinks.k1.prefix = jhxxb: a1.sinks.k1.suffix = :end # Use a channel which buffers events in memory a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # Bind the source and sink to the channel a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
启动
cd /opt/apache-flume-1.9.0-bin bin/flume-ng agent --conf conf/ --name a1 --conf-file /tmp/flume-job/sink/mysink.conf -Dflume.root.logger=INFO,console
向监听端口发送数据
nc 127.0.0.1 4444 123
以上是关于flume 自定义 hbase sink的主要内容,如果未能解决你的问题,请参考以下文章