DAG源在emitFromFromavers上返回false,并且处理器在开始处理之前等待源加载的所有元素

时间:2018-09-27 15:31:45

标签: hazelcast-jet

用例

HazelcastJet版本0.6.1 Hazelcast版本3.10.2

给出此DAG(简化版)

VERTICES

S1 发出5个类型A项的源(通过分区从DB读取) 局部并行度= 1

S2 发出150K类型B项的源(迭代器从DB批量读取100个分区的迭代器) 局部并行度= 1

AD 适应A-> A1和B-> B1类型并一一发射的处理器

FA Processors.filterP仅接受A1类型的项目,并一一发出

FB Processors.filterP仅接受类型为B1的项目,并一一发出

CL 处理器首先累积所有类型为A1的项目,然后在接收到类型为B1的项目时,将其从适当的A1中获取的人员进行充实,然后逐个发出。

WR 水槽写B1 局部并行度= 1

注意: 只是为了给过滤器处理器赋予含义:在DAG​​中,还有其他资源流入同一适配器AD,然后使用过滤器处理器到达其他路径。

边缘

S1->广告

S2->广告

AD-> FA(从序号0开始)

AD-> FB(从序数1开始)

FA-> CL(以优先级0分发并广播的顺序0)

FB-> CL(优先级为1的顺序1)

CL-> WR

问题

如果源S2具有“少量”要加载的项(即15K),则generateFromTraverser永远不会返回false。

如果源S2具有要加载的“许多”项目(即150K),那么在以下情况下,emitFromTraverser将返回false:

  • 所有A1项目均已由CL处理
  • 大约30%的B1项目已经传输到CL,但没有任何项目被CL处理(诊断处理程序日志,该元素已发送到CL但未处理)

S2代码供参考:

protected void init(Context context) throws Exception {
    super.init(context);
    this.iterator = new BQueryIterator(querySupplier, batchSize);
    this.traverser = Traversers.traverseIterator(this.iterator);
}

public boolean complete() {
    boolean result = emitFromTraverser(this.traverser);
    return result;
}

问题

  • CL在源结束之前不处理项目是否正确?
  • 在CL Vertex上使用优先级+分布式+广播是否正确?

更新

似乎从不调用CL边缘1上的completeEdge。 有人可以告诉我为什么吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

您遭受优先级导致的僵局。您的DAG从AD分支,然后以优先级重新加入CL。

AD --+---- FA ----+-- CL
      \          /
       +-- FB --+

设置优先级将导致在处理来自优先级较高边缘的所有项目之前,不会处理来自优先级较低边缘的项目。 AD最终将受到来自较低优先级路径的反压的阻止,CL不会对此进行处理。因此AD被阻止是因为它不能发射到优先级较低的边缘,而CL被阻止了,因为它仍在等待优先级较高的边缘的项目,从而导致死锁。

对于您而言,您可以通过制作2个AD顶点来解决该问题,每个顶点都来自以下一个来源:

S1 --- AD1 ----+--- CL
              /
S2 --- AD2 --+

答案 1 :(得分:0)

一段时间后,我了解了问题所在...

CL处理器无法知道何时所有A1项目都已处理完毕,因为它们全部来自AD处理器。 因此,它需要等待来自AD的所有来源,然后才能开始处理B1项目。

不确定,但是可能在加载了许多项目B之后,DAG中的所有收件箱缓冲区都已满,并且不能接受来自S2的任何其他B,但是同时无法处理B1项目以继续:这就是死锁。

也许DAG能够检测到这一点? 我不太了解Jet,但是收到警告会很好。

也许有一些日志记录要启用?

我希望有人能证实我的回答,并提出改善和发现这些问题的建议。