10

我们的应用程序通过 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。

4

4 回答 4

4

伊甸园收集仍然会导致 STW 暂停,因此 20 毫秒可能是完全正常的,具体取决于活动集的分配行为和堆大小/大小。

于 2011-03-14T21:27:52.730 回答
3

您的 Java 代码是否在 RTLinux 或其他具有硬实时调度能力的发行版下运行?如果不是,处理时间中 10-20 毫秒的抖动似乎是完全合理的,也是意料之中的。

于 2011-03-14T18:23:15.857 回答
2

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

于 2011-06-21T20:54:21.627 回答
1

tcpdump 常见问题解答

数据包的时间戳是什么时候?时间戳的准确性如何?

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

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

于 2011-03-14T18:58:13.087 回答