我有一个应用程序,它通过运行 Solaris 10 的 TCP 将数据从纽约分发到东京。平均吞吐量小于 1Mbps,峰值吞吐量可以达到 20-30Mbps,持续数秒,但典型峰值更接近 10Mbps。单个消息大小很小(~300 字节),延迟一致性是关键。这意味着我们正在尝试删除批处理,也就是说,nagles 已关闭,并且应用程序配置为尽快发送,而不是先排队再发送。
纽约和东京之间的 RTT 为~180ms,TCP 窗口调整为理论吞吐量~40Mbps,即 1M tcp_xmit_hiwat/tcp_rcv_hiwat。tcp_max_buf 和 tcp_cwnd_max 也是 1M。
这里的问题是,我们经常但间歇性地看到神秘的“暂停”,发送方收到 EWOULDBLOCK 导致内部队列中出现累积,然后数据被释放。这里有 2 个问题
- 没有明显的原因导致套接字阻塞,我们似乎没有达到峰值吞吐量,数据包捕获中也没有任何迹象表明速度有任何下降
- 在“放电期”(即当发送方套接字不再阻塞但有要发送的数据缓冲区时),我们会看到消息速率呈稳步增加的锯齿状
前者是问题的关键,如果我能解决这个问题,那么后者就不应该发生。然而后者很奇怪,我天真地以为它会迅速达到峰值吞吐量并保持在那里,直到它处理完积压任务。
CPU 利用率在任何一端都不是问题,SA 表示盒子看起来不错。WAN 链路上的网络拥塞也不是问题,网络表示网络看起来不错。事实上,每个人都说每个单独的部分看起来都很好,只是性能仍然很差!
对于如何优化这种情况,您有什么想法吗?或者需要调查哪些事情可能会对正在发生的事情提供线索?
答案1
EWOULDBLOCK/EAGAIN 表示无法立即发送数据。我们需要有关您的代码的更多详细信息才能解决此问题。
- 尝试弄清楚当 EWOULDBLOCK 返回时发送方发生了什么。检查线程和其他进程,监控内存/交换和 CPU 使用情况。检查日志(/var/messages,...)是否存在任何硬件错误。
- 确定数据包丢失
- 在指控 Solaris TCP 堆栈之前,在另一个操作系统上运行该程序,或者编写一个小型测试程序,以 300B/s 的速度向远程端发送数据(不需要非阻塞套接字,只需发送),检查是否有任何延迟,这将隔离网络问题。
我不是开发人员,但我建议您尝试用 I/O 多路复用器替换非阻塞套接字:选择或轮询或 /dev/poll 并检查套接字是否已准备好写入。它可能会改变程序的行为,使其变得更好,或者在最坏的情况下为您提供更多有关实际问题的调试和提示。
在如此长的距离上,所有数据包可能都使用不同的路由,经过不同的 AS,因此没有人能够真正评估网络质量。由于互联网深处的某个问题(虽然可能很近,否则人们会报告并修复它),数据包可能需要很长时间才能到达并被确认,请尝试从其他位置加入/到其他位置。如果单个数据包需要很长时间才能被确认,则 TCP 窗口将卡住,并且可能无法处理进一步的数据。您可能需要尝试将 TCP 窗口大小调整为更高的值。
另外你也可以简单地运行地铁快速检查网络质量。由于数据包可能采用不同的路径,因此请多运行几次。
希望这能有所帮助:/