我们的应用程序通过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。
答案 0 :(得分:4)
答案 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网络选择器逻辑。如果不对整个系统进行更多分析,我认为不可能做出肯定的原因选择。