Nifi-使用ExecuteStreamCommand进行并行和并发执行

时间:2017-10-03 20:49:16

标签: parallel-processing apache-nifi

目前,我在具有4个核心的边缘节点上运行Nifi。假设我有20个传入的流文件,并且我为ExecuteStreamCommand处理器提供了10个并发任务,这是否意味着我只获得并发执行或并发和并行执行?

1 个答案:

答案 0 :(得分:7)

在这种情况下,您可以获得并发并行性,如Apache NiFi User Guide中所述(强调添加):

  

接下来,Scheduling选项卡提供了一个名为的配置选项   并发任务。 这可以控制处理器的线程数   使用。换句话说,这可以控制FlowFiles的数量   由此处理器同时处理。增加这个值   通常会允许处理器处理更多数据   多少时间。但是,它通过使用系统资源来实现此目的   然后其他处理器无法使用。这基本上提供了一个   处理器的相对权重 - 它控制了多少   系统的资源应分配给此处理器而不是   其他处理器。该字段适用于大多数处理器。那里   但是,某些类型的处理器只能与其一起安排   单个并发任务。

如果您正在调用的命令存在锁定问题或竞争条件,则可能会出现问题,但如果它们是独立的,则仅受JVM调度和硬件性能的限制。

评论中对问题的回答时间太长,无法发表评论:

问题:

  

谢谢安迪。当有4个核心时,我可以假设应该有   4个并行执行,它们将在其中运行多个   线程来处理10个并发任务?以最好的方式,如何   这些20个流文件是在我提到的场景中执行的。 - 约翰30   分钟前

回应:

John,JVM线程处理是一个相当复杂的主题,但是,通常会有 n + C JVM线程,其中 C 是一些常量( >主线程,VM线程,GC线程)和 n number of "individual" threads created by the flow controller to execute the processor tasks。 JVM线程将1:1映射到本机OS线程,因此在运行10个处理器线程的4核系统上,您将进行“4个并行执行”。我的信念是,在高级别,您的操作系统将使用时间切片一次循环10个线程4,每个线程将处理~2个流文件。

同样,非常粗略的想法(假设1个流文件= 1个工作单元= 1秒):

Cores | Threads | Flowfiles/thread | Relative time
  1   |    1    |         20       |      20 s      (normal)
  4   |    1    |         20       |      20 s      (wasting 3 cores)
  1   |    4    |          5       |      20 s      (time slicing 1 core for 4 threads)
  4   |    4    |          5       |       5 s      (1:1 thread to core ratio)
  4   |   10    |          2       |       5+x s    (see execution table below)

如果我们假设每个核心可以处理一个线程,并且每个线程每秒可以处理1个流文件,并且每个线程获得1秒的不间断操作(显然不是真实的),则执行序列可能如下所示:

Flowfiles A - T

核心α,β,γ,δ

主题1 - 10

时间/主题1 s

Time | Core α | Core β | Core γ | Core δ
  0  |   1/A  |   2/B  |   3/C  |   4/D
  1  |   5/E  |   6/F  |   7/G  |   8/H
  2  |   9/I  |  10/J  |   1/K  |   2/L
  3  |   3/M  |   4/N  |   5/O  |   6/P
  4  |   7/Q  |   8/R  |   9/S  |  10/T

在5秒内,所有10个线程都执行了两次,每次完成2个流文件。

但是,假设线程调度程序每次迭代只为每个线程分配0.5秒的循环(再次,不是一个真实的数字,只是为了演示)。然后执行模式是:

Flowfiles A - T

核心α,β,γ,δ

主题1 - 10

时间/话题.5 s

Time | Core α | Core β | Core γ | Core δ
  0  |   1/A  |   2/B  |   3/C  |   4/D
 .5  |   5/E  |   6/F  |   7/G  |   8/H
  1  |   9/I  |  10/J  |   1/A  |   2/B
1.5  |   3/C  |   4/D  |   5/E  |   6/F
  2  |   7/G  |   8/H  |   9/I  |  10/J
2.5  |   1/K  |   2/L  |   3/M  |   4/N
  3  |   5/O  |   6/P  |   7/Q  |   8/R
3.5  |   9/S  |  10/T  |   1/K  |   2/L
  4  |   3/M  |   4/N  |   5/O  |   6/P
4.5  |   7/Q  |   8/R  |   9/S  |  10/T

在这种情况下,总执行时间是相同的(*线程切换有一些开销),但特定的流文件需要“更长”(从0开始的总时间,不是活动的执行时间)才能完成。例如,流程文件C和D在第二个场景中直到 time = 2 才完成,但在第一个场景中 time = 1 完成。

老实说,操作系统和JVM让人们比我更聪明,就像我们的项目一样(幸运的是),所以这里有过度的过度简化,一般来说我会建议你让系统担心超级 - 优化线程。在这种情况下,我不认为将并发任务设置为10会产生很大的改进而不是将其设置为4。您可以阅读有关JVM线程herehere的更多信息。

我刚刚在我的本地1.5.0开发分支中进行了快速测试 - 我将一个简单的GenerateFlowFile运行与0 sec计划连接到LogAttribute处理器。 GenerateFlowFile立即生成如此多的流文件,队列启用了背压功能(暂停输入处理器,直到队列可以排空10,000个等待流文件中的一些)。我停了两个并重新运行了这个,为LogAttribute处理器提供了更多的并发任务。通过将LogAttribute并发任务设置为GenerateFlowFile的2:1,队列永远不会累积超过50个排队的流文件。

Status history of <code>LogAttribute</code> processor

tl; dr 将并发任务设置为您拥有的核心数就足够了。

更新2:

与我们的常驻JVM专家进行了核实,他提到了两件需要注意的事项:

  1. 该命令不仅限于CPU;如果I / O很重,更多并发任务可能是有益的。
  2. 默认情况下,整个流控制器的最大并发任务数设置为10