Java TCP / IP套接字性能问题

时间:2011-03-14 18:15:06

标签: java sockets tcp nio low-latency

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

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

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

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

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

4 个答案:

答案 0 :(得分:4)

eden集合仍然会导致STW暂停,因此20ms可能完全正常,具体取决于分配行为&堆的大小/活动集的大小。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

来自tcpdump faq

  

什么时候打包?怎么样   准确的时间是什么?

     

在大多数操作系统上,tcpdump和   libpcap运行,数据包是时间   加盖作为过程的一部分   网络接口的设备驱动程序,或   处理它的网络堆栈。   这意味着数据包不是时间   它到达时刻印   在网络接口;之后   数据包到达网络   接口,会有延迟,直到   中断传递或   轮询网络接口(即,   网络接口可能不会中断   主机立即 - 司机可能   设置为轮询界面if   网络流量很大,要减少   中断和进程的数量   每个中断更多的数据包),那里   将是一个进一步的延迟之间   中断开始的点   正在处理和时间戳是   生成。

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