ListFTP Processor
描述
列出 FTP 服务器上的文件。 对于在远程服务器上找到的每个文件,将创建一个新的 FlowFile,并将文件名属性设置为远程服务器上文件的名称。 然后可以将其与 FetchFTP 结合使用以获取这些文件。
标签
属性
| 名称 | 默认值 | 可选值 | 描述 |
|---|---|---|---|
| Listing Strategy | timestamps |
| 指定如何确定新的/更新的实体。 有关详细信息,请参阅每个策略的说明。 |
| Hostname | | 远程系统的完全限定主机名或 IP 地址 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Port | 21 | 连接到远程主机以从中获取数据的端口 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Username | | 用户名 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Password | | 用户帐户的密码 敏感属性:是 支持表达式语言:是(使用 FlowFile 属性与环境/系统变量求值) | |
| Remote Path | . | 远程系统上从中拉取或推送文件的路径 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Record Writer | | 控制器服务 API:RecordSetWriterFactorycn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8 | 指定用于创建列表的记录写入器。如果未指定,将为每个列出的实体创建一个 FlowFile。如果指定了记录写入器,所有实体将写入单个 FlowFile,而不是将属性添加到各个 FlowFile。 |
| Search Recursively | false |
| 如果为 true,将从任意嵌套的子目录中提取文件; 否则,不会遍历子目录 |
| Follow Symbolic Links | false |
| 如果为 true,则甚至会拉取符号文件以及嵌套的符号子目录; 否则,不会读取符号文件,也不会遍历符号链接子目录 |
| File Filter Regex | | 提供Java正则表达式用于过滤文件名; 如果提供了过滤器,则仅获取名称与正则表达式匹配的文件 | |
| Path Filter Regex | | 当'递归搜索'为 true 时,仅扫描路径匹配给定正则表达式的子目录 | |
| Ignore Dotted Files | true |
| 如果为 true,名称以点开头的文件('.')将被忽略 |
| Remote Poll Batch Size | 5000 | 指定在远程系统上执行文件列表时,在给定目录中查找多少个文件路径。此值通常不需要修改,但在对包含大量文件的远程系统进行轮询时,此值可能至关重要。设置过高会导致性能很差,设置过低会导致流程比正常情况慢。 | |
| Connection Timeout | 30 sec | 创建连接时超时之前等待的时间量 | |
| Data Timeout | 30 sec | 在本地和远程系统之间传输文件时,该值指定允许在系统之间不传输任何数据的时间长度 | |
| Connection Mode | Passive |
| FTP 连接方式 |
| Transfer Mode | Binary |
| FTP传输模式 |
| Proxy Configuration Service | | 控制器服务 API:ProxyConfigurationServicecn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8 | 指定代理配置 Controller Service 来代理网络请求。 |
| Internal Buffer Size | 16KB | 设置缓冲数据流的内部缓冲区大小 | |
| 目标系统时间戳精度 | auto-detect |
| 指定目标系统的时间戳精度。由于此处理器使用实体的时间戳来决定应该列出哪些内容,因此使用正确的时间戳精度至关重要。 |
| Entity Tracking State Cache | | 控制器服务 API:DistributedMapCacheClientcn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8 | 已列出的实体存储在指定的缓存中, 以便该处理器能够在 Lynxus 重启或主节点变更后恢复列举。 'Tracking Entities' 策略需要跟踪最近 'Tracking Time Window' 内所有已列出实体的信息。 为支持大量实体,该策略使用 DistributedMapCache 而非托管状态。 缓存键格式为 'ListedEntities::{processorId}(::{nodeId})'。 如果按节点跟踪已列出的实体,则会添加可选的 '::{nodeId}' 部分以分别管理状态。 例如,集群范围缓存键 = 'ListedEntities::8dda2321-0164-1000-50fa-3042fe7d6a7b', 单节点缓存键 = 'ListedEntities::8dda2321-0164-1000-50fa-3042fe7d6a7b::lynxus-node3'。 存储的缓存内容是经过 Gzip 压缩的 JSON 字符串。 当目标列举配置发生变化时,缓存键将被删除。 由 'Tracking Entities' 策略使用。 |
| Entity Tracking Time Window | 3 hours | 指定该处理器应跟踪已列出实体的时长。 'Tracking Entities' 策略可以选取时间戳位于指定时间窗口内的任何实体。 例如,若设为 '30 minutes',则该处理器运行时,最近 30 分钟内带有时间戳的任何实体都将成为列举目标。 当满足以下任一条件时,已列出的实体被视为 'new/updated' 并发出一个 FlowFile: 1. 不存在于已列出的实体中, 2. 时间戳比缓存的实体更新, 3. 大小与缓存的实体不同。 如果某个缓存实体的时间戳早于指定的时间窗口,该实体将从缓存的已列出实体中移除。 由 'Tracking Entities' 策略使用。 支持表达式语言:是(仅使用环境/系统变量求值) | |
| Entity Tracking Initial Listing Target | all |
| 指定应如何处理初始列举。 由 'Tracking Entities' 策略使用。 |
| Use UTF-8 Encoding | false |
| 告诉客户端在处理文件和文件名时使用 UTF-8 编码。 如果设置为 true,服务器还必须支持 UTF-8 编码。 |
关系 (Relationships)
| 名称 | 描述 | 自动终止 |
|---|---|---|
success | 所有收到的 FlowFiles 都会成功路由 | 否 |
写入的 FlowFile 属性
| 名称 | 描述 |
|---|---|
ftp.remote.host | FTP 服务器的主机名 |
ftp.remote.port | 连接到 FTP 服务器上的端口 |
ftp.listing.user | 执行 FTP 列表的用户的用户名 |
file.owner | 源文件的数字所有者 ID |
file.group | 源文件的数字组 ID |
file.permissions | 源文件的读/写/执行权限 |
file.size | 源文件中的字节数 |
file.lastModifiedTime | 文件系统中文件的时间戳last modified as 'yyyy-MM-dd'T'HH:mm:ssZ' |
filename | FTP 服务器上的文件名 |
path | 从中提取文件的 FTP 服务器上目录的完全限定名称 |
状态管理
| 作用域 | 描述 |
|---|---|
| CLUSTER | 执行文件列表后,存储最新文件的时间戳。这允许处理器在下次运行时仅列出在此日期之后添加或修改的文件。状态跨集群存储,以便此处理器可以仅在主节点上运行,如果选择了新的主节点,新节点不会重复上一个主节点列出的数据。 |
受限 (Restricted)
该组件不受限。
输入要求
该组件不允许有传入连接。
详细说明
ListFTP
ListFTP 会对 FTP 服务器上配置目录中遇到的所有文件执行列表(listing)操作。常见的用例大致可分为两类。
流式用例
默认情况下,该 Processor 会为目录中的每个文件创建一个独立的 FlowFile,并添加 filename、path 等 Attribute。一个常见用法是把 ListFTP 连接到 FetchFTP Processor。这两个 Processor 配合使用, 可以方便地监视目录,并在任何新文件到达 FTP 服务器时以高效的流式方式获取其内容。
批处理用例
另一个常见用例是:希望处理给定目录中所有新到达的文件,并且只有当所有文件都处理完成之后才执行 某些操作。上述流式数据的处理方式使这一点变得困难,因为 Lynxus 本质上是一个流式平台,不存在 有明确起点和终点的"作业",数据只是在可用时被拾取。
为解决这一问题,ListFTP Processor 可以可选地配置一个 Record Writer。配置 Record Writer 后, 只会创建单个 FlowFile,其中为目录中的每个文件包含一条 Record,而不是每个文件一个 FlowFile。 在这种模式下,要获取每个文件的内容,必须先把记录拆分为独立的 FlowFile,然后再逐个获取。 那么这样做有什么帮助呢?
我们仍然可以实现"等待目录中所有文件处理完毕"的目标:把 FlowFile 拆开,并在一个 Process Group 中处理所有数据。将 Process Group 的 FlowFile Concurrency 配置为 "Single FlowFile per Node", 意味着一次只会有一个 FlowFile 进入该 Process Group。进入之后,这个 FlowFile 可以被拆分并逐部分 处理。再将 Process Group 的 Outbound Policy 配置为 "Batch Output",意味着在所有数据处理完成 之前,任何 FlowFile 都不会离开该 Process Group。
在这个流程中,我们用 ListFTP 对目录做列表操作。该 Processor 配置了一个 Record Writer(本例 使用 CSV Writer,但任何 Record Writer 都可以),这样整个列表只会生成一个 FlowFile。这份列表 随后被发送到 "Process Listing" Process Group(如下所示)。只有当整个目录的内容都处理完毕后, 数据才会离开 "Process Listing" Process Group。此时,当 Process Group 中的所有数据都已准备 离开时,每个处理完成的文件会被发送到 "Post-Processing" Process Group;同时,原始的列表会被 发送到 "Processing Complete Notification" Process Group。要实现这一点,Process Group 必须 配置 FlowFile Concurrency 为 "Single FlowFile per Node"、Outbound Policy 为 "Batch Output"。
在 "Process Listing" Process Group 中,列表通过 "Listing" Input Port 接收,然后直接发送到 "Listing of Processed Data" Output Port,以便在所有处理完成时,原始列表也一并输出。
接下来,列表被拆分为每条记录一个独立的 FlowFile。因为我们要用 FetchFTP 获取数据,所以需要把 文件的 filename 和 path 作为 FlowFile Attribute。实现方式有几种,最简单的机制是使用 PartitionRecord Processor。该 Processor 配置了一个能够读取 ListFTP 所写数据的 Record Reader (本例为 CSV Reader),并配置了两个额外的用户自定义属性:
path: /pathfilename: /filename
这样,进入 PartitionRecord Processor 的每条记录都会被拆分为一个独立的 FlowFile(因为
"path" 与 "filename" 字段的组合对每条记录都是唯一的),"filename" 和 "path" 记录字段会成为
FlowFile 上的 Attribute。FetchFTP 的 "Remote File" 属性配置为使用 ${path}/${filename},
从而利用这些 Attribute。
最后,我们处理数据——本例中只是用 GZIP 压缩——并把输出发送到 "Processed Data" Output Port。 数据会在这里排队,直到所有数据都准备好离开 Process Group 时才一并释放。
Record Schema
当 Processor 配置为使用 Record Writer 写出列表时,Record 会使用以下 schema(Avro 格式)写出:
{
"type": "record",
"name": "lynxusRecord",
"namespace": "cn.org.acal.lynxus",
"fields": [
{
"name": "filename",
"type": "string"
},
{
"name": "path",
"type": "string"
},
{
"name": "directory",
"type": "boolean"
},
{
"name": "size",
"type": "long"
},
{
"name": "lastModified",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
}
},
{
"name": "permissions",
"type": [
"null",
"string"
]
},
{
"name": "owner",
"type": [
"null",
"string"
]
},
{
"name": "group",
"type": [
"null",
"string"
]
}
]
}