nifi利用官方expression-language,实现变更flowfile内数据的ETL应用

Nifi Mutate FlowFile Content Processor

该项目主要是应用官方expression-language(EL)实现类似logstash-plugins-filters-mutate的功能

项目地址 https://github.com/cclient/nifi-mutate-bundle

功能描述

适于于 flowfile为文本数据,一行一个json 'JSON-per-line' format

对每行一条json对象string的flowfile,按行应用mutate规则,修改原始json对象的值,输出变更后的flowfile

应用原理

首先nifi官方 EL 默认可以应用在 'Variable Registry and FlowFile Attributes'上

查看源码和开发自定义Processor的经验可知应用 EL 方法为propertyValue.evaluateAttributeExpressions(flowFile)

evaluateAttributeExpressions有多个重载方法,其中一项为

public PropertyValue evaluateAttributeExpressions(Map<String, String> attributes)

查看nifi源码和实际验证知evaluateAttributeExpressions(Map<String, String> attributes)可以应用在任何Map<String, String>上

因此只要能将flowfile content转换为Map<String,String>,便可对flowfile content应用官方 EL

这点很容易,一行一条json对象string是比较常见的数据传输格式,例如(file,kafka,elasticsearch,logstash event等各种数据组件)

逐行读取flowfile,每行转为json对象后转换为Map<String,String>结构,应用官方 EL 取值,以一定的规则应用新值更改原始json后,把新的flowfile输出


目前转换规则封装的只是应用 EL 取出value后的行为,取value本身完全依赖官方EL

官方EL支持操作'Variable Registry and FlowFile Attributes',通过这种方式更改flowfile的content,增大了官方EL的应用场景

转换规则配置方式为json obj 目前只支持最外层key,a.b.c类的多级结构后续再支持

EL执行后的值内容为PropertyValue,丢失了类型信息,因此取值后都需再指定一次targetType作类型转换,targetType参照logstash-plugins-filters-mutate-convert

目前支持targetType: boolean、string、integer、long、float、double,后期扩展其他类型

目前支持行为

  • 1 delete key 删除key {"test_delete_key":{"operate":"remove"}}

  • 2 add key 不存在该key则新增 {"test_value_sum":{"el":"${test_value_key1:plus(${test_value_key2}):plus(${test_value_key3})}","targetType":"long"}}

  • 3 replace/update value 存在该key则更新 {"test_update_value": {"el": "2","targetType": "string"}}

  • 4 rename key 更改key名称(实际为添加一个新key,并删除旧key) {"rename_key": {"el": "${test_rename_key}","targetType": "string","orginalKey": "test_rename_key","operate": "remove"}}

demo

原始json string

{
    "test_delete_key": 1,
    "test_update_value": "1 to 2",
    "test_rename_key": "test_rename_key -> rename_key",
    "test_value_key1": 200,
    "test_value_key2": 200,
    "test_value_key3": 4,
    "test_value_toUpper": "cclient@hotmail.com",
    "test_value_timeStampToStr": "1590117918909"
}

转换规则

{
    "test_delete_key": {
        "operate": "remove"
    },
    "test_update_value": {
        "el": "2",
        "targetType": "string"
    },
    "rename_key": {
        "el": "${test_rename_key}",
        "targetType": "string",
        "orginalKey": "test_rename_key",
        "operate": "remove"
    },
    "test_value_toUpper": {
        "el": "${test_value_toUpper:toUpper()}",
        "targetType": "string"
    },
    "test_value_timeStampToStr": {
        "el": "${test_value_timeStampToStr:format(\"yyyy/MM/dd\", \"GMT\")}",
        "targetType": "string"
    },
    "test_value_sum": {
        "el": "${test_value_key1:plus(${test_value_key2}):plus(${test_value_key3})}",
        "targetType": "long"
    }
}

变更后

{
    "test_delete_key": 1,
    "test_update_value": "2",
    "test_value_key1": 200,
    "test_value_key2": 200,
    "test_value_key3": 4,
    "test_value_toUpper": "CCLIENT@HOTMAIL.COM",
    "test_value_timeStampToStr": "2020/05/22",
    "rename_key": "test_rename_key -> rename_key",
    "test_value_sum": 404
}

需求

数据处理会有对原始数据做微调的场景,过去通过大量logstash的filter实现

较为常用logstash filter有mutate,split,aggregate等,复杂场景通过写ruby代码和自定义filter解决

logstash很优秀,但随着更定制功能的需求,长期使用下也累积了一些使用上的痛点,通过logstash本身较难低成本的解决,调研学习nifi后,逐步将部分数据流迁移至nifi生态

最大的痛点

该Processor用来实现较为初级的数据微调需求

实际难度不高,主要创新点是把官方通常只应用在'Variable Registry and FlowFile Attributes'的EL,扩展应用在FlowFile Content上

项目只是展示可行性,实际可以更进一步的定制和添加功能

deploy

1 compile

mvn package -Dmaven.test.skip=true

2 upload to one of

nifi.nar.library.directory=./lib
nifi.nar.library.directory.custom=./lib_custom
nifi.nar.library.autoload.directory=./extensions
nifi.nar.working.directory=./work/nar/

cp nifi-mutate-nar/target/nifi-mutate-nar-0.1.nar nifi/lib_custom/

3 restart nifi if need

nifi/bin/nifi.sh restart

posted @ 2021-02-28 21:41  cclient  阅读(613)  评论(0编辑  收藏  举报