我们在 Windows 7
上看到 ZeroMQ 出现奇怪且无法解释的现象,通过 TCP 发送消息。(或通过 inproc
,因为 ZeroMQ 在 Windows 上在内部使用 TCP 进行信号传输。
现象是前500条消息到达的速度越来越慢,延迟稳步上升。然后延迟下降,消息始终快速到达,但 CPU/网络争用导致的峰值除外。
此处描述了问题:https://github.com/zeromq/libzmq/issues/1608
一直是500条消息。如果我们没有延迟地发送,那么消息会被分批处理,所以我们会看到这种现象会持续数千次发送。如果我们在发送之间延迟,我们会更清楚地看到图表。即使在发送之间延迟多达 50-100 毫秒也不会改变事情。
消息大小也无关紧要。我用 10 字节的消息和 10K 的消息进行了测试,结果相同。
最大延迟始终为 2 毫秒(2,000 微秒)。
在 Linux 机器上我们没有看到这种现象。
我们想要做的是消除这条初始曲线,以便消息以其正常的低延迟(大约 20-100 微秒)离开新连接。
Update: the issue does not show on Windows 10 nor 8. It seems to happen only on Windows 7.
最佳答案
我们已找到原因和解决方法。这是 Windows 7(至少)上所有 TCP 事件的一个普遍问题,由接收端的缓冲引起。您可以在“TCP 慢启动”下在线找到一些提示。
在一个新的连接上,或者如果连接空闲了(我认为)150 毫秒或更长时间,接收方缓冲传入的数据包并且不将这些提供给应用程序,直到接收缓冲区是已满和/或某些超时到期(不清楚)。
我们在 ZeroMQ 中使用 TCP 套接字进行线程间信号传输的解决方法是在新信号对上发送一个虚拟数据 block 。这会强制 TCP 堆栈“正常”工作,然后我们会看到大约 100-150 微秒的一致延迟。
我不确定这是否普遍有用;对于大多数应用程序来说,在接收时稍等片刻是有利可图的,这样 TCP 堆栈就可以向调用应用程序传递更多信息。
但是对于发送许多小消息的应用程序,此解决方法可能会有所帮助。
请注意,如果连接空闲,慢速启动会再次发生,因此连接应该每 100 毫秒左右检测一次,如果这很关键的话。
关于tcp - 为什么 Windows7 上的 TCP/IP 需要 500 次发送才能预热? (w10,w8 证明没有受到影响),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33409749/