Apache storm 为什么Trident在这个最小的示例中不调用ack()或fail()?
我试着用三叉戟制作一个小例子。我们的目标是观察元组在发生故障时是如何重放的。下面是拓扑定义Apache storm 为什么Trident在这个最小的示例中不调用ack()或fail()?,apache-storm,trident,Apache Storm,Trident,我试着用三叉戟制作一个小例子。我们的目标是观察元组在发生故障时是如何重放的。下面是拓扑定义 Random rand = new Random(); Config config = new Config(); config.setDebug(true); config.setNumWorkers(1); TridentTopology topology = new TridentTopology();
Random rand = new Random();
Config config = new Config();
config.setDebug(true);
config.setNumWorkers(1);
TridentTopology topology = new TridentTopology();
topology.newStream("spout", new RandomIntegerSpout())
.map((MapFunction) tridentTuple -> {
if ((tridentTuple.getLongByField("msgid") % 50 == 0) &&
(rand.nextInt(2) == 1)) {
System.out.println(String.format("Failed to process tuple %d", tridentTuple.getLongByField("msgid")));
throw new ReportedFailedException("Divisible by 50");
}
return new Values(tridentTuple.toArray());
})
.peek((Consumer) tridentTuple -> System.out.println(tridentTuple.getValues()));
我使用storm starter中的RandomIntegerSpout
,它扩展了BaseRichSpoot
,只生成随机数。然后,我应用一个MapFunction
,它只是每隔50个元组抽取一个随机数,然后随机使元组失败
问题是,我没有得到任何ack
s或fail
s
我玩了一下喷口,在调试模式下运行它,尝试了相同的示例输出,用标准风暴螺栓进行了尝试。锚定工作正常,只是没有被三叉戟召唤
我在1.2.3版和2.0.0版中用LocalCluster和StormSubmitter重现了这个问题
下面是Storm UI的屏幕截图:
与map ack和fail元组对应的螺栓如预期的那样失败,但这永远不会传播回喷口
我认为三叉戟mastercoord可能会期望某种状态下的持久性来实现拓扑结构的完成,但是用某种persistentAggregate替换peek并没有帮助。我还排除了map
中的一个bug,方法是对每个
执行相同的操作
通过检查发现代码几乎微不足道,我可能误解了Trident/Storm的一些基本内容。如果批量完成,我期望trident调用喷口的和
ack
方法是错误的吗?我意识到在IBatchSpout
中没有fail
方法。Trident如何处理批次的重放???Trident Spoots不会在单个元组级别确认或失败元组。相反,元组作为一个批进行确认
三叉戟喷口通常看起来像
其思想是Trident将管理批次元组的ACK/FAILES跟踪,然后如果批次失败,它将要求喷口重复批次,如果没有,它根本不会
请注意,这与标准雨水口有何不同。对于普通的喷口,框架基本上会告诉喷口“嘿,发射一些东西。你发射什么取决于你自己”,然后使用ack
和fail
方法告诉喷口是否应该再次发射特定的元组
使用Trident时,喷口被告知“嘿,(重新)发出批次号x”,然后由喷口知道该批次中有哪些元组。使用此模型,不需要fail
方法。一些三叉戟喷口将有一个ack/succeed
方法,允许喷口放弃与特定进行中批次相关的任何状态
对于包装的IRichSpouts
,有一些将它们包装到Trident API中。基本上,包装器调用nextTuple
,直到拥有完整的批处理,然后将ID存储在缓存中。如果要求包装器重新提交一批,它将在喷口上调用fail
。否则,一旦批处理成功,它将调用ack
我认为你在Storm UI中没有看到与此相关的任何内容的原因是,IRichBolt
实际上没有在那里表示出来。相反,它是被包装的,因此ack/fail
调用在spoot-spoot
组件内部的“引擎盖下”发生。如果您想确定是否正在调用ack/fail,请尝试在IRichSpout
的ack/fail
方法中添加一些日志记录
M emitPartitionBatch(TransactionAttempt tx, TridentCollector collector, PartitionT partition, M lastPartitionMeta);