nifi作为一个数据管道类开源项目,在处理数据流上拥有非常大的优势,功能强大、性能优秀且有着不错的健壮性,但作为ETL工具使用对于流式数据处理存在一些不足(比如合并流、CEP等),而flink则非常擅长该领域,通过nifi和flink进行对接可以补足这些不足,nifi与flink数据交换最简单的方式是通过中间件(如kafka),但是通过这种方式将需要维护大量的topic或者queue,而且增加一个中间环节也显得不那么直接,徒增了一些不稳定因素,增加了部署和维护的难度,而nifi提供了site to site的能力,而flink也有现成的nifi的connector(包含sourc和sink)的实现,但网上相关资料较少:
flink关于nifi connector使用官方文档 http://flink.iteblog.com/dev/connectors/nifi.html
nifi相关配置文件官方文档 https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#site_to_site_properties
下面就是通过site to site完成nifi和flink互传的简单demo。
一、nifi配置文件配置
只需要配置nifi.properties的nifi.remote.input.socket.port即可,指定一个用于site to site的端口号,但这样的传输是非安全的,如有安全性需要可以按照官方文档配置nifi.remote.input.secure等。
二、nifi流程配置
如图:
该流程的in和out组件需要配置在nifi的最外层,Data for Flink代表portName,flink中会用到,in和out的portName可以重名,本例中GenerateFlowFile只输出一个字符串"test"。
三、flink依赖及代码
首先添加flink依赖,如果不清楚flink开发相关可以看我的其他博客,里面有做说明,首先是nifi connector的依赖:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-nifi_2.11</artifactId>
<version>${flink.version}</version>
</dependency>
因为代码比较简单,下面直接上代码,如果有不清楚的地方可以参考我的另一篇关于flink的source和sink的文章,代码如下:
public class NifiTest {
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
SiteToSiteClientConfig clientConfig = new SiteToSiteClient.Builder()
.url("http://localhost:8080/nifi")
.portName("Data for Flink")
.requestBatchCount(5)
.buildConfig();
SourceFunction<NiFiDataPacket> nifiSource = new NiFiSource(clientConfig);
DataStream<NiFiDataPacket> stream = env
.addSource(nifiSource)
.map(s -> s);
SinkFunction<NiFiDataPacket> nifiSink = new NiFiSink<>(clientConfig, new NiFiDataPacketBuilder<NiFiDataPacket>() {
@Override
public NiFiDataPacket createNiFiDataPacket(NiFiDataPacket niFiDataPacket, RuntimeContext runtimeContext) {
return new NiFiDataPacket() {
@Override
public byte[] getContent() {
return (new String(niFiDataPacket.getContent()) + " from flink").getBytes(StandardCharsets.UTF_8);
}
@Override
public Map<String, String> getAttributes() {
return niFiDataPacket.getAttributes();
}
};
}
});
stream.addSink(nifiSink);
env.execute();
}
}
其中http://localhost:8080/nifi是nifi的地址,端口号为nifi启动占用的端口号而非nifi.remote.input.socket.port指定的端口号,个人猜测应该是nifi会先根据portName做一些处理然后再通过nifi.remote.input.socket.port的端口建立connect。
四、运行结果
启动flink的demo程序: