风暴,螺栓延迟和总延迟之间的巨大差异?
Storm, huge discrepancy between bolt latency and total latency?
下面是我的拓扑结构的 Storm UI 的屏幕截图。这是在拓扑完成处理 10k 条消息后拍摄的。
(拓扑配置有 4 个 worker 并使用 KafkaSpout)。
我的螺栓 "process latency" 的总和约为 8100 毫秒,拓扑的完整延迟要长得多,为 115881 毫秒。
我知道此类差异可能是由于资源争用或与 Storm 内部结构相关的原因造成的。我相信资源争用在这里不是问题; GC 在此测试期间根本没有 运行,分析显示我有大量可用的 CPU 资源。
所以我认为问题是我在某种程度上滥用了 Storm 的内部机制。有什么建议在哪里看?
元组必须在某处等待,可能在喷口中;是等待发送到拓扑还是等待消息被处理后被确认?
可能我应该调整ackers的数量(我已经将ackers设置为4,与worker的数量相同)?
还有关于如何解决此问题的其他一般性建议吗?
*请注意,在其进程和执行延迟之间存在较大差异的一个螺栓实现了滴答螺栓、批处理模式。所以这种差异是意料之中的。
*编辑。
我怀疑差异可能涉及消息在完全处理后被 Spout 确认。如果我在处理过程中刷新 Storm UI,与 Spouts 的确认数相比,我最终 Bolt 的确认数增加得非常快。尽管这可能是由于 Spout 确认的消息比最终的 Bolt 少得多;最后一个螺栓确认的几百条消息可能代表 Spout 中的一条消息。但是,我想我应该提到这种怀疑,以征求意见是否有可能,即 Spout 的 acker 任务正在溢出。
可能有多种原因。首先,你需要了解这个数字是如何衡量的。
- Spout Complete Latency:发出元组直到
Spout.ack()
被调用的时间。
- Bolt 执行延迟:运行
Bolt.execute()
. 所需的时间
- 螺栓处理延迟:调用时间
Bolt.execute()
,直到螺栓确认给定的输入元组。
如果您不立即确认 Bolt.execute
中的每个传入输入元组(这绝对没问题),处理延迟 可能比 高得多执行延迟.
此外,处理延迟不能加起来等于完整延迟,因为元组可以留在内部input/output缓冲区中.这会增加额外的时间,直到完成最后一个确认,从而增加 完整延迟 。此外,ackers 需要处理所有传入的 ack 并通知 Spout 有关已完全处理的元组。这也增加了完全延迟。
问题可能是运算符之间的大型内部缓冲区。这可以通过增加 dop(并行度)或设置参数 TOPOLOGY_MAX_SPOUT_PEDING
来解决——这会限制拓扑中元组的数量。因此,如果有太多元组在飞行中,喷口将停止发送元组,直到收到确认为止。因此,元组不会在内部缓冲区中排队,完全延迟 会下降。如果这没有帮助,您可能需要增加 ackers 的数量。如果 ack 的处理速度不够快,ack 可能会缓冲,从而增加 完整延迟 。
下面是我的拓扑结构的 Storm UI 的屏幕截图。这是在拓扑完成处理 10k 条消息后拍摄的。
(拓扑配置有 4 个 worker 并使用 KafkaSpout)。
我的螺栓 "process latency" 的总和约为 8100 毫秒,拓扑的完整延迟要长得多,为 115881 毫秒。
我知道此类差异可能是由于资源争用或与 Storm 内部结构相关的原因造成的。我相信资源争用在这里不是问题; GC 在此测试期间根本没有 运行,分析显示我有大量可用的 CPU 资源。
所以我认为问题是我在某种程度上滥用了 Storm 的内部机制。有什么建议在哪里看?
元组必须在某处等待,可能在喷口中;是等待发送到拓扑还是等待消息被处理后被确认?
可能我应该调整ackers的数量(我已经将ackers设置为4,与worker的数量相同)?
还有关于如何解决此问题的其他一般性建议吗?
*请注意,在其进程和执行延迟之间存在较大差异的一个螺栓实现了滴答螺栓、批处理模式。所以这种差异是意料之中的。
*编辑。 我怀疑差异可能涉及消息在完全处理后被 Spout 确认。如果我在处理过程中刷新 Storm UI,与 Spouts 的确认数相比,我最终 Bolt 的确认数增加得非常快。尽管这可能是由于 Spout 确认的消息比最终的 Bolt 少得多;最后一个螺栓确认的几百条消息可能代表 Spout 中的一条消息。但是,我想我应该提到这种怀疑,以征求意见是否有可能,即 Spout 的 acker 任务正在溢出。
可能有多种原因。首先,你需要了解这个数字是如何衡量的。
- Spout Complete Latency:发出元组直到
Spout.ack()
被调用的时间。 - Bolt 执行延迟:运行
Bolt.execute()
. 所需的时间
- 螺栓处理延迟:调用时间
Bolt.execute()
,直到螺栓确认给定的输入元组。
如果您不立即确认 Bolt.execute
中的每个传入输入元组(这绝对没问题),处理延迟 可能比 高得多执行延迟.
此外,处理延迟不能加起来等于完整延迟,因为元组可以留在内部input/output缓冲区中.这会增加额外的时间,直到完成最后一个确认,从而增加 完整延迟 。此外,ackers 需要处理所有传入的 ack 并通知 Spout 有关已完全处理的元组。这也增加了完全延迟。
问题可能是运算符之间的大型内部缓冲区。这可以通过增加 dop(并行度)或设置参数 TOPOLOGY_MAX_SPOUT_PEDING
来解决——这会限制拓扑中元组的数量。因此,如果有太多元组在飞行中,喷口将停止发送元组,直到收到确认为止。因此,元组不会在内部缓冲区中排队,完全延迟 会下降。如果这没有帮助,您可能需要增加 ackers 的数量。如果 ack 的处理速度不够快,ack 可能会缓冲,从而增加 完整延迟 。