繁体   English   中英

Java TCP / IP套接字性能问题

[英]Java TCP/IP Socket Performance Problem

我们的应用程序是通过Java中的TCP / IP套接字非常快速地读取数据。 我们正在使用带有非阻塞套接字和选择器的NIO库来指示读取的准备情况。 平均而言,读取和处理读取数据的总处理时间是亚毫秒。 然而,我们经常看到10-20毫秒的尖峰。 (在Linux上运行)。

使用tcpdump,我们可以看到tcpdump读取2条谨慎消息之间的时差,并将其与我们的应用程序时间进行比较。 我们看到tcpdump似乎没有延迟,而应用程序可以显示20毫秒。

我们非常确定这不是GC,因为GC日志几乎没有显示Full GC,而且在JDK 6中(根据我的理解),默认GC是并行的,所以它不应该暂停应用程序线程(除非执行Full GC) 。

它看起来几乎像Java的Selector.select(0)方法有一些延迟返回准备读取,因为在TCP层,数据已经可以读取(并且tcpdump正在读取它)。

附加信息:在峰值负载时,我们每条消息处理大约6,000 x 150字节平均值,或每秒大约900 MB。

eden集合仍然会产生STW暂停,因此20ms可能完全正常,具体取决于实时集的分配行为和堆大小/大小。

您的Java代码是在RTLinux下运行,还是其他一些具有硬实时调度功能的发行版? 如果没有,处理时间内10-20毫秒的抖动似乎是完全合理的,并且是预期的。

我在我工作的java服务中遇到了同样的问题。 当从客户端重复发送相同的请求时,服务器将在流中的相同位置阻塞25-35ms。 在套接字中关闭Nagle的算法为我修复了这个问题。 这可以通过在Socket上调用setTcpNoDelay(true)来完成。 这可能导致网络拥塞增加,因为ACK现在将作为单独的数据包发送。 有关Nagle算法的更多信息,请参见http://en.wikipedia.org/wiki/Nagle%27s_algorithm

tcpdump faq

什么时候是一个时间戳? 时间准确度如何准确?

在大多数运行tcpdump和libpcap的操作系统中,数据包都带有时间戳,作为网络接口设备驱动程序或网络堆栈处理过程的一部分。 这意味着数据包在到达网络接口时没有加盖时间戳; 在数据包到达网络接口之后,将会有一个延迟,直到中断被传递或网络接口被轮询(即,网络接口可能不立即中断主机 - 如果网络可以设置驱动程序轮询接口流量很大,以减少中断次数并在每次中断时处理更多数据包),并且在中断开始处理的时间点和生成时间戳之间会有进一步的延迟。

很可能,时间戳是在特权内核层中进行的,丢失的20ms是将上下文切换回用户空间以及Java和JVM网络选择器逻辑。 如果不对整个系统进行更多分析,我认为不可能做出肯定的原因选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM