我正在使用apachestorm开发一个实时图像处理应用程序,它需要极低的延迟。在拓扑定义中,每1s一个喷口将发射原始图像(5mb),几个螺栓将处理它们。每个螺栓的处理延迟是可以接受的,总的计算延迟可以在150ms左右。
但是,我发现不同节点上的工作进程之间的消息传递延迟非常高。在5个连续的bolt上,总的延迟大约是200ms。为了计算这个延迟,我从端到端延迟中减去所有的任务延迟。此外,我还实现了一个计时器螺栓,其他处理螺栓将在这个计时器螺栓中注册,以便在开始真正的处理之前记录时间戳。通过比较螺栓的时间戳,我发现每个螺栓之间的延迟很高,正如我之前注意到的那样。
为了分析这种高附加延迟的来源,我首先将发送间隔缩短为1s,这样就不会因为高计算开销而出现排队延迟。另外,在storm ui中,我发现没有一个bolt的cpu利用率很高。
然后,我检查了网络延迟。我使用的是一个1gbps的网络测试平台,通过rtt和带宽对网络进行测试。要发送5mb映像,网络延迟应该不会太高。
最后,我考虑的是缓冲区延迟。我发现每个线程都维护自己的发送缓冲区,并将数据传输到工作者的发送缓冲区。我不知道需要多长时间接收器螺栓才能收到这个发送消息。按照社区的建议,我将发送方/接收方缓冲区大小增加到16384,将storm\u netty\u message\u batch\u size修改为32768。然而,这没有帮助。
我的问题是,如何消除/减少bolt之间的消息传递开销?(inter-workers)有可能同步bolt之间的通信,并让接收方立即毫不延迟地获得发送消息吗?
3条答案
按热度按时间tez616oj1#
通过在storm的源代码中插入时间戳的详细基准测试,我发现在传递两个1440x1080图像时,“序列化”步骤需要30毫秒。如果我纯粹地把一个字节数组传递到一个元组中,我认为这个步骤可以被删除,从而减少延迟。。。
oxcyiej72#
对于低延迟,您可能需要调整netty缓冲区和传输批大小。某些延迟可能是由于当前工作进程的消息传递和线程模型所固有的。
同时尝试调整中断器配置:
拓扑.disruptor.wait.timeout.millis
拓扑.disruptor.batch.size
拓扑.disruptor.batch.timeout.millis
也就是说,社区正在努力通过重新设计消息传递子系统来提高延迟和吞吐量。看到了吗https://github.com/apache/storm/pull/2502
eh57zj3b3#
根据你上面的评论,你在每条消息中包含大约5mb的图像。
我不太了解kafka/storm,但我的理解是它是一个主流的消息代理。这类系统的设计不是为了处理大型有效负载,主要是因为它们提供了有关传递和持久性的保证,这两种保证都需要某些处理步骤,在大多数情况下,这些步骤会多次缓冲字节流。这会导致随着大小的增加,延迟的时间增长大于线性增长。
我的建议是将图像存储在couchbase或memcached之类的快速工具中,然后发送一条包含指向它的指针的消息。这样的设置不难在一天之内启动并运行。