1. 引言
Apache NiFi是一个易于使用、功能强大、安全可靠的数据处理和分发系统, 可用于自动化管理不同系统之间的数据流(dataflow)。NiFi 基于 Web 界面定 义数据处理流程,并由后台在服务器上进行调度。NiFi支持从多种数据源动态拉 取数据,可以轻松完成数据同步工作。本文档将简单介绍一些NiFi的基础概念, 并说明如何安装配置和实现一些常见的数据处理场景。 2. 核心概念
NiFi的设计理念与基于流程的编程fbp(Flow Based Programming)的 主要思想密切相关。 2.1 基本术语
2.1.1 FlowFile
FlowFile表示在数据处理过程中流动的每个对象,也就是我们要处理的数 据,它包括一组属性键值对(attributes,如uuid、filename、path等)和字 节内容(content,即数据本身)。 2.1.2 FlowFile Processor
FlowFile处理器用于完成对数据的实际处理工作,包括但不限于对数据内容 和属性的加载、路由、转换、输出等。 NiFi内置了上百个处理器,基本覆盖了常见的数据处理场景。从功能上来看, 处理器可以大致分为数据提取、数据转换、数据路由、数据库访问、属性提取等 类型,我们将简单介绍一些典型的处理器。 2.1.2.1 数据提取
 GetFile:监控本地磁盘或者网络连接磁盘中的文件夹,读取文件内容并 将其封装为一个FlowFile,会忽略没有读取权限的文件;  GetFTP:获取 FTP 服务器上的文件,封装 FlowFile 并将源文件删除, 主要用于移动文件,而不是复制文件;  GetSFTP:获取SFTP服务器上的文件,封装FlowFile并将源文件删除,
主要用于移动文件,而不是复制文件;  GetJMSQueue:从ActiveMQ JMS消息队列读取消息;  GetJMSTopic:从 ActiveMQ JMS消息队列的Topic读取消息,包括持 久订阅和非持久订阅;  ListenUDP:监听传入的UDP数据包,并为每个数据包或每一组数据包 创建一个FlowFile;  ListenTCP:监听TCP连接,并使用行分隔符读取数据;  GetHDFS:监视HDFS指定的目录,每当有新文件进入HDFS时,就会 创建一个 FlowFile 并将其从 HDFS 中删除;如果该处理器在群集中运行,为了 保持数据的完整性,只能允许在主节点上运行;  ConsumeKafka:消费Kafka消息。 2.1.2.2 数据转换
 CompressContent:使用指定的压缩算法压缩或解压缩流文件内容;  ConvertCharacterSet:转换流文件内容的字符集;  EncryptContent:加密或解密流文件;  ReplaceText:通过正则表达式来替换匹配规则的部分流文件内容;  TransformXml:将 XSLT 文件(可扩展样式表转换语言,Extensible Stylesheet Language Transformations)转换为XML文件;  JoltTransformJSON:使用Jolt规范转换JSON内容。 2.1.2.3 数据路由
 ControlRate: 控制数据流传输到后续处理器的速率;  DetectDuplicate: 根据自定义的条件,监测重复的FlowFile;  DistributeLoad:根据分发策略将流文件分发给下游处理器,可用于实 现负载均衡或数据抽样;  MonitorActivity:当我们定义的时间范围内没有收到任何数据流时发送 通知,或者在数据流恢复时发送通知;  RouteOnAttribute:基于FlowFile的属性路由数据;
 ScanAttribute: 扫描FlowFile上的自定义属性,检查是否有属性与自定 义的词典相匹配,从而路由数据;  ScanContent:扫描FlowFile的内容,检查是否存在自定义的词典条目, 从而路由数据,该词典可以包含文本条目或二进制条目;  RouteOnContent:搜索FlowFile的内容,检查是否与自定义的正则表 达式匹配,根据匹配结果路由数据;  ValidateXml:使用 XML Schema 验证 FlowFile 的内容,根据数据的 有效性来路由。 2.1.2.4 数据库访问
 ExecuteSQL:执行自定义的 SQL 语句,并将返回结果转换为 Avro 格 式的FlowFile;  PutSQL:执行FlowFile内容中定义的SQL DML(Insert、Update 或 Delete)语句,FlowFile属性可以作为参数,用于构建SQL语句;  ConvertJSONToSQL:将 JSON 转化为 Insert 或者 Update 语句,并 将其发送给PutSQL处理器;  GetMongo: 在 Mongo 数据库中执行自定义的查询语句,并将返回结 果封装为一个FlowFile;  PutMongo:将FlowFile内容写入到MongoDB。  SelectHiveQL:在 Apache Hive 数据库中执行自定义的 HiveQL 查询 语句,将并结果封装为Avro或CSV格式的FlowFile;  PutHiveQL:在 Apache Hive 数据库中执行 FlowFile 内容中定义的 HiveQL DDM语句。 2.1.2.5 属性提取
 EvaluateXPath: 使用 XPath 路径表达式对 XML 格式的 FlowFile 内容 进行计算,用计算结果替换FlowFile内容,或者将其提取到自定义的属性中;  EvaluateXQuery:使用 XQuery 语言对 XML 格式的 FlowFile 内容进 行计算,用计算结果替换FlowFile内容,或者将其提取到自定义的属性中;
 EvaluateJsonPath: 使用 JSONPath(XPath 在 JSON 中的应用)表达 式对JSON格式的FlowFile内容进行计算,用计算结果替换FlowFile内容,或 者将其提取到自定义的属性中;  ExtractText: 使用一个或多个正则表达式从FlowFile内容中提取数据, 用于替换FlowFile内容,或者将其提取到自定义的属性中;  HashAttribute:对自定义的属性列表串联执行哈希函数;  HashContent:对FlowFile内容执行哈希函数,并将结果添加为属性;
 IdentifyMimeType:基于FlowFile内容判定其MIME类型;  UpdateAttribute:向FlowFile添加或更新任意数量的自定义属性,常 用于添加静态属性值或使用表达式语言动态计算的属性值。 2.1.2.6 系统交互
 ExecuteProcess: 执行操作系统命令(比如Linux的Shell命令),并将 执行结果封装为一个FlowFile;此处理器为源处理器,且不接受参数输入;  ExecuteStreamCommand:将输入的FlowFile内容作为命令,并将命 令的执行结果输出为新的FlowFile。 2.1.2.7 拆分与合并
 SplitText:根据配置的规则(比如用换行符分割)将接收到的单个文本 FlowFile拆分为1个或多个FlowFile;  SplitJson:将复杂的JSON对象(比如由数组或多个子对象组成)的拆 分为单个JSON元素的FlowFile;  SplitXml:将XML格式的FlowFile拆分为多个;  UnpackContent:解压缩不同类型的存档格式,比如 Zip、Tar 等,将 解压缩后的每个文件作为新的FlowFile;  SegmentContent:根据配置的数据大小,基于字节偏移将FlowFile拆 分为较小的FlowFile;可用于并行发送不同的片段来提高传输性能,下游接收到 的这些 FlowFiles还可以通过MergeContent处理器重新组装;  MergeContent:根据规则将多个FlowFile合并为一个FlowFile;
 SplitContent:根据指定内容拆分FlowFile。 2.1.2.8 数据输出
 PutEmail:向配置的邮件地址发送电子邮件,FlowFile内容可以作为附 件发送;  PutFile:将FlowFile内容写入本地(或网络连接)的文件夹中;  PutFTP:将FlowFile内容复制到远程FTP服务器中;  PutSFTP:将FlowFile内容复制到远程SFTP服务器中;  PutJMS:将 FlowFile 内容作为 JMS 消息发送到 JMS 代理,还可以选 择将FlowFile属性作为JMS属性;  PublishKafka:将FlowFile内容作为消息发送到Kafka。 2.1.2.9 HTTP
 GetHTTP:执行 HTTP 或 HTTPS 请求,并将结果作为一个 FlowFile, 处理器可以记录上次请求时间,以确保不会重复获取数据;  PostHTTP:将FlowFile内容作为参数执行HTTP POST请求;  ListenHTTP:启动HTTP或HTTPS服务器并监听传入的连接,将POST 请求内容将作为FlowFile内容,并返回200响应;  InvokeHTTP:执行已配置的HTTP请求;  HandleHttpRequest/HandleHttpResponse:HandleHttpRequest 处 理器是一个源处理器,会启动一个类似于 ListenHTTP 的嵌入式 HTTP(S)服 务器, 用HTTP请求创建一个FlowFile, HandleHttpResponse能够在FlowFile 处理完成后将响应发送回客户端。 2.1.3 Connection
Connection用于连接处理器,其充当了一个队列的角色,可以用来临时保 存FlowFile在JVM内存中的位置。Connection可以设置负载上限(FlowFile 个数或占用JVM内存总大小),如果超出阈值,则上游处理器将停止执行(即为 背压机制),所以也可以将Connection理解为一个缓冲区。另外,还可以在 Connection中配置FlowFile的处理优先级。
2.1.4 Flow Controller
Flow Controller是NiFi的核心,它为处理器(Processor)提供线程资源, 同时管理处理器的调度执行。 2.1.5 Process Group
顾名思义,一堆处理器及其连接可以组成一个Process Group,我们可以 通过简单地组合不同的组件,来得到一个具有全新功能的组件。 2.2 整体架构
NiFi的整体架构如下图所示:
2.2.1 Web Server
Web Server提供了基于HTTP的命令和可视化用户界面,使得我们可以方 便地创建、修改和监控数据处理流程。 2.2.2 Flow Controller
如上所述,Flow Controller是整个数据处理流程的核心。 2.2.3 Extensions
NiFi支持自定义扩展Processor。
2.2.4 Repositories
NiFi使用了三个存储库(Repositories), 均为本地存储上的目录,用于保 存Flow File数据。 2.2.4.1 FlowFile Repository
FlowFile Repository存储的是当前使用的所有FlowFile的元数据,包括属 性、状态(比如此时属于哪个队列)和内容的指针,相当于为我们提供了数据处 理流程的最新状态,因此FlowFile Repository可以用来做故障恢复工具。 在数据处理流程的每个步骤中,对FlowFile进行修改之前,NiFi会将其以 预写日志的方式(Write-Ahead Log)记录在FlowFile Repository中。 2.2.4.2 Content Repository
Content Repository是存储FlowFile内容的库,因此其数据量要远远大于 另外两个库。Content Repository中存放的内容是只读的,也就说FlowFile的 内容一旦写到磁盘上,就不会被更新,直到数据过期,如果需要修改FlowFile 的内容,NiFi将复制一份新的数据进行操作,这样可以最大幅度的保证数据处理 的吞吐量和数据的任意状态重放,也便于历史数据的查询和回放。 2.2.4.3 Provenance Repository
Provenance Repository是存储所有FlowFile历史记录的地方,为每一条 数据都提供了数据血统图。每当FlowFile被创建、克隆、修改时,就会产生一 条Provenance Event,每一条Provenance Event都存放了FlowFile的所有属 性和指向FlowFile内容的指针。Provenance Repository 会存放一段时间内的 Provenance Event,可用于查看血统图和回放数据。