Apache nifi apachenifi中的批处理流文件

Apache nifi apachenifi中的批处理流文件,apache-nifi,Apache Nifi,我已经编写了自定义nifi处理器,它尝试批处理输入流文件 然而,它的行为似乎并不像预期的那样。发生的情况如下: 我在服务器上复制粘贴一些文件FethFromServerProcessor从服务器获取这些文件并将其放入queue1MyCustomProcessor从queue1批量读取文件。我在MyCustomProcessor上定义了batchSize属性,在其onTrigger()方法中,我通过执行以下操作从当前批中的queue1获取所有流文件: session.get(context.get

我已经编写了自定义nifi处理器,它尝试批处理输入流文件

然而,它的行为似乎并不像预期的那样。发生的情况如下:

我在服务器上复制粘贴一些文件
FethFromServerProcessor
从服务器获取这些文件并将其放入
queue1
MyCustomProcessor
queue1
批量读取文件。我在
MyCustomProcessor
上定义了
batchSize
属性,在其
onTrigger()
方法中,我通过执行以下操作从当前批中的
queue1
获取所有流文件:

session.get(context.getProperty(batchSize).asInteger())
onTrigger()
的第一行创建时间戳,并在所有流文件上添加此时间戳。因此,批处理中的所有文件都应该具有相同的时间戳。然而,这并没有发生。通常,第一个流文件得到一个时间戳,其余的流文件得到另一个时间戳


似乎当
FetchFromServerProcessor
从服务器获取第一个文件并将其放入
queue1
时,
MyCustomProcessor
会被触发,并从队列中获取所有文件。顺便说一句,以前只有一个文件,这是该批中唯一的一个文件。当
MyCustomProcessor
处理此文件时,
FetchFromServerProcessor
已从服务器中获取所有文件,并将它们放入
队列1
。因此,在处理第一个文件后,
MyCustomProcessor
获取
queue1
中的所有文件,并形成第二批,而我希望在单个批中提取所有文件


如何避免形成两个批次?我看到人们在这种情况下讨论等待通知:。但我不能很快理解这些帖子。有人能给我一些使用wait-notify处理器来实现这一点的最简单的步骤吗?或者有人能给我一些介绍使用wait-notify处理器的步骤的最简单的教程吗?我解释过,等待通知模式也是解决批处理相关问题的标准方法吗?或者有其他标准方法来完成这项工作吗?

听起来好像此批量大小是
CustomProcessor
的传入流文件的所需计数,那么为什么不编写
CustomProcessor\onTrigger()
,如下所示:

@Override
public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
    final ComponentLog logger = getLogger();
    // Try to get n flowfiles from incoming queue
    final Integer desiredFlowfileCount = context.getProperty(batchSize).asInteger();
    final int queuedFlowfileCount = session.getQueueSize().getObjectCount();
    if (queuedFlowfileCount < desiredFlowfileCount) {
        // There are not yet n flowfiles queued up, so don't try to run again immediately
        if (logger.isDebugEnabled()) {
            logger.debug("Only {} flowfiles queued; waiting for {}", new Object[]{queuedFlowfileCount, desiredFlowfileCount});
        }
        context.yield();
        return;
    }

    // If we're here, we do have at least n queued flowfiles
    List<FlowFile> flowfiles = session.get(desiredFlowfileCount);

    try {
        // TODO: Perform work on all flowfiles
        flowfiles = flowfiles.stream().map(f -> session.putAttribute(f, "timestamp", "my static timestamp value")).collect(Collectors.toList());
        session.transfer(flowfiles, REL_SUCCESS);

        // If extending AbstractProcessor, this is handled for you and you don't have to explicitly commit
        session.commit();
    } catch (Exception e) {
        logger.error("Helpful error message");
        if (logger.isDebugEnabled()) {
            logger.error("Further stacktrace: ", e);
        }
        // Penalize the flowfiles if appropriate (also done for you if extending AbstractProcessor and an exception is thrown from this method
        session.rollback(true);
        //  --- OR ---
        // Transfer to failure if they can't be retried
        session.transfer(flowfiles, REL_FAILURE);
    }
}
(告诉处理器延迟对特定流文件执行工作)和让步(告诉处理器等待一段时间再尝试执行任何工作)是很重要的


您可能还希望在自定义处理器上运行,以确保没有多个线程在运行,从而可能出现争用情况

您能否描述一种逻辑来确定队列是否不完整?因为它可能完全不同。从你的话听起来,你只需要添加一些延迟和回滚,以防你在
session.get(n)
中得到太“年轻”的文件,它是什么
FetchFromServerProcessor
FetchFromServerProcessor
可以是从远程服务器获取文件的任何东西,比如SFTP服务器或Amazon S3,所以一个接一个地获取文件并将它们放入
queue1
需要时间。我目前没有逻辑来确定队列是否不完整。问题是它应该是什么逻辑?我不能指望有什么耽搁,对吗?(因为我不能确定通过网络获取当前批中的所有文件需要多少时间)。我可以将服务器上的文件数作为流文件的属性,但我如何使用它呢?似乎您需要更改FetchFromServerProcessor的逻辑。。。因为只有这个处理器知道它什么时候结束……安迪,在你的回答中重新扩展Java8是多么有礼貌。
        for (int i = 0; i < flowfiles.size(); i++) {
            // Write the same timestamp value onto all flowfiles
            FlowFile f = flowfiles.get(i);
            flowfiles.set(i, session.putAttribute(f, "timestamp", "my timestamp value"));
        }