一、NIFI简介
Apache NiFi 是一个强大的开源数据集成工具,主要用于自动化数据流的管理和处理。它提供了丰富的图形化界面和流式数据处理能力,可以帮助用户快速设计和管理数据流,从而实现数据的收集、转换、路由、存储等操作。
NiFi 的基本功能包括数据流的定义、实时数据处理、数据格式转换、批量处理等。它适用于各种场景,如物联网数据流处理、大数据管道集成、日志聚合、数据同步和数据迁移等。无论是处理批量数据还是实时数据,NiFi 都能为用户提供灵活、可扩展且可靠的解决方案。
与传统的 ETL 工具相比,NiFi 最大的特点是其流式架构和强大的可视化操作界面,允许用户通过拖拽式的方式构建数据流,而无需编写大量的代码。NiFi 在数据流设计的直观性和易用性方面具有显著优势,尤其适合复杂的数据集成和实时流数据处理场景。
二、场景介绍
这里通过一个日常常用场景来了解NIFI的功能。
读取aws s3 bucket中的日志文件,然后将日志文件写入到es中进行记录,同时针对日志中的某些关键字进行分析,将符合条件的日志单独再记录到额外的es index中。
这个场景是很贴合实际使用的一个场景,借助这个场景来看下NIFI怎么对于数据进行采集,清洗和传递的。
三、功能实现
功能规划
按照如下processor规划进行设计
| 功能 | NIFI Processsor | 描述 |
|---|---|---|
| 采集aws s3 bucket object | ListS3 | 获取bucket中的object list |
| FetchS3Object | 获取object的内容并且写入到nifi中 | |
| 处理bucket object文件记录处理数据格式 | SplitJson | 根据jsonpath来将json array处理成为单独的json object(根据s3 object内容按需使用) |
| EvaluateJsonPath | 从 JSON 数据中提取特定的字段值,并将其作为属性(attributes)附加到NIFI flowfile中 | |
| 对不同类型数据进行路由处理 | RouteOnAttribute | 根据不同条件来进行路由处理 |
| 将日志记录写入es组件 | PutElasticseachJson | 写入数据到es中 |
| NIFI日志组建记录操作记录 | LogAttribute | 记录日志 |
这里可以先看下最终全局的workflow,在实现步骤分布解析处理细节配置
s3 bucket object示例数据展示
为了节省篇幅后续节点数据以“...”代替
[
{
"id": "0718b3f94d0e1ce8aa1bc169ee160fba378f7b1c",
"reply_id": "0718b3f94d0e1ce8aa1bc169ee160fba378f7b1c",
"project_id": 2898,
"commit_id": null,
"confidential": false,
"diff_discussion": false,
"expanded": true,
"for_commit": false,
"individual_note": true,
"resolvable": false,
"discussion_path": null,
"resolved": false,
"resolved_by_push": false,
"resolved_by": null,
"resolved_at": null,
"resolve_path": "/ACD/TC/ic/cf/-/merge_requests/1/discussions/0718b3f94d0e1ce8aa1bc169ee160fba378f7b1c/resolve",
"resolve_with_issue_path": "/ACD/TC/ic/cf/-/issues/new?discussion_to_resolve=0718b3f94d0e1ce8aa1bc169ee160fba378f7b1c&merge_request_to_resolve_discussions_of=1",
"notes": [
{
"id": "1980891",
"type": null,
"attachment": null,
"author": {
"id": 832,
"username": "marek.duk",
"name": "Marek duk",
"state": "active",
"locked": false,
"avatar_url": "https://secure.gravatar.com/avatar/cb22b4409fe3fadf3e6a7f062f8941402f42cfc4407e965ed1f171b37292f29b?s=80&d=identicon",
"status_tooltip_html": null,
"show_status": false,
"availability": null,
"path": "/marek.duk",
"bot": false
},
"created_at": "2024-10-15T12:02:48.813Z",
"updated_at": "2024-10-15T12:02:48.817Z",
"system": true,
"noteable_id": 219894,
"noteable_type": "MergeRequest",
"project_id": 2898,
"resolvable": false,
"confidential": false,
"internal": false,
"noteable_iid": 1,
"commands_changes": {},
"external_author": null,
"note": "assigned to @marek.duk",
"note_html": "<p data-sourcepos=\"1:1-1:24\" dir=\"auto\">assigned to <a href=\"/marek.duk\" data-reference-type=\"user\" data-user=\"832\" data-container=\"body\" data-placement=\"top\" class=\"gfm gfm-project_member js-user-link\" title=\"Marek duk\">@marek.duk</a></p>",
"current_user": {
"can_edit": false,
"can_award_emoji": true,
"can_resolve": false,
"can_resolve_discussion": false
}
}
]
},
...
]
实现步骤
listS3
配置bucket并且绑定Aws credentials service,这里采用accesskey进行身份验证。
FetchS3Object
配置拉取s3 object配置复用Lists3Aws credentials service服务进行认证,bucket等其他属性使用默认值从lists3 processor的attribute中获取。
SplitJson
配置处理s3 object文件内容拆分逻辑,由于我的原始数据是json array的形式保存在s3的文件中,因此这里直接使用"$"对跟路径进行split操作,拆分后的json为json array中的单个element(json object)。
这一步数据处理需要结合自己实际业务进行灵活调整
EvaluateJsonPath
配置author属性从json中读取路径为.notes[0].authro.name
RouteOnAttribute
配置两个属性author_marek和author_troyqu,分别对应两个路由条件用来匹配日志记录中带有marek和troyqu字样的记录。这里是从EvaluateJsonPath中atttribute中的author字段的内容进行判断。
定义路由propeties后会对应出现符合路由的relationships,可以根据路由条件定义下一步操作。
PutElasticseachJson
写入nifi_local index
写入nifi_local_troyqu index,对应记录中包含"troyqu"关键字的记录
写入nifi_local_marek index,对应记录中包含"marek"关键字的记录
es认证service配置
数据写入es中
LogAttribute
这里配置LogAttribute可以查看最终日志方便进行回溯和查看。
Connection
在connection中可以配置背压(防止节点任务过载)等参数,通过背压等属性可以灵活调整节点负载。
背压:当节点任务处理缓慢,当达到背压阈值之后nifi会控制数据写入,防止过载
四、总结
- 这里可以看到nifi提供了全功能来实现抓取s3数据到es或者其他消费组件,可以结合自己业务需要来处理,nifi提供了丰富的组件支持。
- 在使用nifi的时候connection之间可以配置背压等参数来调整负载。
- 示例中的最终节点都是logattribute但是实际中需要考虑到最终一致性,以及结合业务要求针对异常记录进行最终一致性或者告警。