元组动态重定向的 Apache Storm 问题(对端到端延迟的莫名其妙的影响)
Apache Storm issue with Dynamic redirection of tuples (baffling impact on end-to-end latency)
下面我包含了解释我在 Storm 中遇到的问题的文字。无论如何,我知道它很长 post(请注意),任何 comment/indication 都非常受欢迎。有描述:
我在一台服务器上安装了 Storm 0.9.4 和 ZooKeeper 3.4.6(2 个插槽,Intel Xeon 8 核芯片,96 GB 内存 运行ning CentOS)并且我设置了一个伪-分布式单节点 Storm 运行 时间。我的配置包括 1 个 zookeeper 服务器、1 个 nimbus 进程、1 个主管进程和 1 个工作进程(提交拓扑时),所有 运行 都在同一台机器上。我实验的目的是查看 Storm 在单个节点设置上的行为,当输入负载在执行程序线程之间动态分配时。
出于实验目的,我输入了由 1 个长值和 1 个整数值组成的元组。输入数据来自两个从磁盘文件中读取元组的 spout,我控制输入速率以遵循以下模式:
前 24 秒 200 tuples/second(时间 0 - 24 秒)
接下来的 12 秒(24 - 36 秒)800 tuples/second
200 tuples/sec 再持续 6 秒(时间 36 - 42 秒)
转向我的拓扑结构,我有两种类型的螺栓:a) 从两个 spout 接收输入的 Dispatcher 螺栓,以及 (b) 对元组执行操作并将一些元组维护为状态的消费者螺栓。 Dispatcher 的并行性提示是一个 (1 executor/thread),因为我已经检查过它从未达到其容量的 10%。对于 Consumer bolt,我有两个并行提示(对于该 bolt,2 executors/threads)。选择我之前提到的输入速率,以便我使用 Consumer bolt 上适当数量的执行器来监控端到端延迟小于 10 毫秒。详细地说,我有 运行 与一个消费者执行器相同的拓扑,它可以处理 200 tuples/sec 的输入速率,端到端延迟 < 10 毫秒。同样,如果我再添加一个消费者执行器(总共 2 个执行器),拓扑可以消耗 800 tuples/sec,端到端延迟小于 10 毫秒。在这一点上,我不得不说,如果我使用 1 个消费者执行器 800 tuples/sec,端到端延迟会达到 2 秒。顺便说一句,我不得不提到我使用我的螺栓的 ack() 函数测量端到端延迟,并查看在拓扑中发送元组到其元组树被完全确认之间需要多少时间。
正如您现在意识到的那样,目标是通过模拟添加另一个消费者 executor.In 订单来模拟除了输入尖峰的处理资源,我使用直接分组,在尖峰之前,我只将元组发送到两个消费者执行器之一。当在 Dispatcher 上检测到峰值时,它也开始向另一个 Consumer 发送元组,以便在两个线程之间平衡输入负载。因此,我希望当我开始将元组发送到额外的消费者线程时,端到端延迟将回落到其可接受的值。然而,之前的情况并没有发生。
为了验证我的假设,即两个消费者执行器能够在峰值期间保持 < 10 毫秒的延迟,我执行了相同的实验,但是这次,我在整个生命周期内向两个执行器(线程)发送元组的实验。在这种情况下,端到端延迟保持稳定并处于可接受的水平。所以,我不知道我的模拟中到底发生了什么。在将输入负载重定向到其他消费者执行程序的情况下,我真的无法弄清楚是什么导致端到端延迟恶化。
为了更多地了解 Storm 的机制,我在一台较小的机器上进行了相同的设置并进行了一些分析。我看到大部分时间都花在了lmax disruptor的BlockingWaitStrategy上,它支配了CPU。我的实际处理函数(在 Consumer bolt 中)只占用了 lmax BlockingWaitStrategy 的一小部分。因此,我认为这是队列之间的 I/O 问题,与消费者中元组的处理无关。
知道哪里出了问题,我得到了这种 radical/baffling 行为吗?
谢谢。
首先,感谢您提出详细且精心设计的问题!我这边有很多评论(不确定这是否已经是答案...):
- 你的实验时间很短(时间范围低于 1 分钟),我认为这可能无法揭示可靠的数字。
- 如何检测峰值?
- 你对 Storm 的内部缓冲机制感到敬畏吗(看这里:http://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/)
- 你配置了多少个acker?
- 我假设在您的峰值期间,在您检测到峰值之前,缓冲区已填满并且需要一些时间来清空它们。因此延迟不会立即下降(可能会延长你上次的时间来解决这个问题)。
- 很多人都使用ack机制,但是不够精确。首先,它显示一个 平均值 值(使用 平均值、分位数或最大值 会好得多。此外,度量值不是什么毕竟应该考虑延迟。例如,如果您将元组保持在内部状态一段时间并且在元组从状态中删除之前不确认它,Storm 的 "latency" 值会增加不会使延迟测量的意义。延迟的通常定义是获取结果元组的输出时间戳并减去源元组的发出时间戳(如果有多个源元组,则使用最年轻的——即最大—— -timestamp over all source tuples)。棘手的部分是为每个输出元组找出相应的源元组......作为替代方案,有些人注入带有发射时间戳的虚拟元组作为数据。这个虚拟元组由每个转发operator 立即并且 sink operator 可以很容易地竞争一个延迟值,因为它可以访问 emit 时间戳随身携带。如前所述,这是对实际延迟的一个很好的近似。
希望这对您有所帮助。如果您有更多问题 and/or 信息,我可以稍后完善我的答案。
下面我包含了解释我在 Storm 中遇到的问题的文字。无论如何,我知道它很长 post(请注意),任何 comment/indication 都非常受欢迎。有描述:
我在一台服务器上安装了 Storm 0.9.4 和 ZooKeeper 3.4.6(2 个插槽,Intel Xeon 8 核芯片,96 GB 内存 运行ning CentOS)并且我设置了一个伪-分布式单节点 Storm 运行 时间。我的配置包括 1 个 zookeeper 服务器、1 个 nimbus 进程、1 个主管进程和 1 个工作进程(提交拓扑时),所有 运行 都在同一台机器上。我实验的目的是查看 Storm 在单个节点设置上的行为,当输入负载在执行程序线程之间动态分配时。
出于实验目的,我输入了由 1 个长值和 1 个整数值组成的元组。输入数据来自两个从磁盘文件中读取元组的 spout,我控制输入速率以遵循以下模式: 前 24 秒 200 tuples/second(时间 0 - 24 秒) 接下来的 12 秒(24 - 36 秒)800 tuples/second 200 tuples/sec 再持续 6 秒(时间 36 - 42 秒) 转向我的拓扑结构,我有两种类型的螺栓:a) 从两个 spout 接收输入的 Dispatcher 螺栓,以及 (b) 对元组执行操作并将一些元组维护为状态的消费者螺栓。 Dispatcher 的并行性提示是一个 (1 executor/thread),因为我已经检查过它从未达到其容量的 10%。对于 Consumer bolt,我有两个并行提示(对于该 bolt,2 executors/threads)。选择我之前提到的输入速率,以便我使用 Consumer bolt 上适当数量的执行器来监控端到端延迟小于 10 毫秒。详细地说,我有 运行 与一个消费者执行器相同的拓扑,它可以处理 200 tuples/sec 的输入速率,端到端延迟 < 10 毫秒。同样,如果我再添加一个消费者执行器(总共 2 个执行器),拓扑可以消耗 800 tuples/sec,端到端延迟小于 10 毫秒。在这一点上,我不得不说,如果我使用 1 个消费者执行器 800 tuples/sec,端到端延迟会达到 2 秒。顺便说一句,我不得不提到我使用我的螺栓的 ack() 函数测量端到端延迟,并查看在拓扑中发送元组到其元组树被完全确认之间需要多少时间。
正如您现在意识到的那样,目标是通过模拟添加另一个消费者 executor.In 订单来模拟除了输入尖峰的处理资源,我使用直接分组,在尖峰之前,我只将元组发送到两个消费者执行器之一。当在 Dispatcher 上检测到峰值时,它也开始向另一个 Consumer 发送元组,以便在两个线程之间平衡输入负载。因此,我希望当我开始将元组发送到额外的消费者线程时,端到端延迟将回落到其可接受的值。然而,之前的情况并没有发生。
为了验证我的假设,即两个消费者执行器能够在峰值期间保持 < 10 毫秒的延迟,我执行了相同的实验,但是这次,我在整个生命周期内向两个执行器(线程)发送元组的实验。在这种情况下,端到端延迟保持稳定并处于可接受的水平。所以,我不知道我的模拟中到底发生了什么。在将输入负载重定向到其他消费者执行程序的情况下,我真的无法弄清楚是什么导致端到端延迟恶化。
为了更多地了解 Storm 的机制,我在一台较小的机器上进行了相同的设置并进行了一些分析。我看到大部分时间都花在了lmax disruptor的BlockingWaitStrategy上,它支配了CPU。我的实际处理函数(在 Consumer bolt 中)只占用了 lmax BlockingWaitStrategy 的一小部分。因此,我认为这是队列之间的 I/O 问题,与消费者中元组的处理无关。
知道哪里出了问题,我得到了这种 radical/baffling 行为吗?
谢谢。
首先,感谢您提出详细且精心设计的问题!我这边有很多评论(不确定这是否已经是答案...):
- 你的实验时间很短(时间范围低于 1 分钟),我认为这可能无法揭示可靠的数字。
- 如何检测峰值?
- 你对 Storm 的内部缓冲机制感到敬畏吗(看这里:http://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/)
- 你配置了多少个acker?
- 我假设在您的峰值期间,在您检测到峰值之前,缓冲区已填满并且需要一些时间来清空它们。因此延迟不会立即下降(可能会延长你上次的时间来解决这个问题)。
- 很多人都使用ack机制,但是不够精确。首先,它显示一个 平均值 值(使用 平均值、分位数或最大值 会好得多。此外,度量值不是什么毕竟应该考虑延迟。例如,如果您将元组保持在内部状态一段时间并且在元组从状态中删除之前不确认它,Storm 的 "latency" 值会增加不会使延迟测量的意义。延迟的通常定义是获取结果元组的输出时间戳并减去源元组的发出时间戳(如果有多个源元组,则使用最年轻的——即最大—— -timestamp over all source tuples)。棘手的部分是为每个输出元组找出相应的源元组......作为替代方案,有些人注入带有发射时间戳的虚拟元组作为数据。这个虚拟元组由每个转发operator 立即并且 sink operator 可以很容易地竞争一个延迟值,因为它可以访问 emit 时间戳随身携带。如前所述,这是对实际延迟的一个很好的近似。
希望这对您有所帮助。如果您有更多问题 and/or 信息,我可以稍后完善我的答案。