我有一个应用程序,它定期需要发送当前状态的快照,当前状态将由大约500,000个64字节消息表示。我很难使用ZMQ快速可靠地发送和接收这么多消息。
我一直在tcp上使用PUB / SUB来做这个,但是我不会拘泥于模式或协议,只要它能完成工作。在我的实验中,我专注于使用发送和接收高水位标记,发送和接收缓冲区设置,以及向发送循环添加一些睡眠以尝试将其减慢一点。对我来说设置似乎相当慷慨(500K HWM,10MB缓冲区)并且仅使用环回连接,消息仍然不能一直接收。
我对这些或其他调整参数的适当设置感兴趣,更广泛地了解如何推断各种设置的效果。
可能有助于提供适当答案的一些进一步细节:
分布是一对多。预计接收人数约为20人。
每条消息代表一组有关不同金融工具的信息,所有信息都同时被观察到。在我看来,可以将它们组合成一个大消息(所有消息的集合在逻辑上构成一个完整的快照)并将它们分开(客户可能只对某些仪器感兴趣,我认为这会有所帮助)更容易过滤掉它们)。
消息的预期频率基本上不会超过每20毫秒,并且不会慢于5秒。我实际降落的地方可能会受到性能考虑因素的影响(即,我的服务器实际上可以将消息抽出多快以及哪种数据速率对客户来说是压倒性的)。
答案 0 :(得分:5)
让我们打破这一点。
首先,为什么HWM没有“正常工作”:
HWM不是一个确切的限制,因为内部缓冲区由两个独立的线程填充和清空,并且当有大量活动时,可用空间的计数可能会滞后很多。 0MQ zmq_setsockopt手册页说:“0MQ不保证套接字会接受与ZMQ_SNDHWM消息一样多的数量,并且实际限制可能会低多达60-70%,具体取决于套接字上的消息流。”
其次,你为什么要丢失消息:
当您将0.5M消息(x 20)转储到套接字缓冲区时,您将随机命中HWM,然后PUB套接字的行为将丢弃它无法排队的消息。
第三,如何解决这个问题:
将状态分解为单独的消息是没有理由的;唯一的理由是,如果国家不适应记忆,那很容易。发送为multipart(ZMQ_SNDMORE);这会创建一个有效的消息,在传出缓冲区中占用1个插槽。
然后,删除你的500K HWM限制并恢复到默认值(1000),这将是绰绰有余。
第四,如何获得更好的表现:
显然,尽可能地描述和改进您的发布商和订阅者代码;这些是通常的瓶颈。
然后,如果消息稀疏,请考虑对消息进行某种形式的压缩,并且可以在没有太多CPU成本的情况下执行此操作。在20个订户中,您通常会从网络开销中获得更多,而不会因为CPU成本而损失。
最后,如果您增加到更多用户并且它是一个关键系统,请查看PGM多播,这将有效地消除网络成本。
答案 1 :(得分:1)
经过一天的半随机试验和各种组合后,我得出以下初步结论:
在发送循环中添加睡眠语句以限制消息速率,基本上可以使用任何一组选项来提高可靠性。
将500,000条消息作为单条消息的帧发送而不是500条单独的消息,可以提高可靠性。
使用epgm而不是tcp协议可以实现更高的吞吐量。
使用epgm,多播速率选项需要匹配睡眠语句所需的消息速率。
增加高水位标记和缓冲区有助于提高可靠性,但您必须增加两个设置,并在客户端和服务器上执行此操作。如果所有这些都不是组合完成的,那么往往没有帮助。您必须将这些设置为相当高,以使任何类型的可靠性与单个消息一起运行(而不是单个消息的帧)。在这种情况下,在我将高水位设置为1,000,000且缓冲区设置为65 MB之前,我没有得到好的结果。 (我试图发送的消息集的大小的两倍。)这比我本能地想要尝试的要高得多。那个案例在每轮500K消息之间暂停5秒。将间隔时间缩短到1秒,我不得不将它们推得更高,达到单批邮件大小的4倍。
使用epgm,恢复间隔设置无济于事。