我们正在运行一个分布式 Java 服务器系统(操作系统:Linux),通过 TCP 进行大量计算。虽然我们的流量模式不是突发性,在某些机器上,我们会看到网络带宽使用率出现波动,如下所示:
02:56:32 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
02:56:33 PM lo 61.00 61.00 8.69 8.69 0.00 0.00 0.00
02:56:33 PM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
02:56:33 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
02:56:34 PM lo 107.00 107.00 13.70 13.70 0.00 0.00 0.00
02:56:34 PM eth0 15514.00 15794.00 8036.93 7148.15 0.00 0.00 0.00
02:56:34 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
02:56:35 PM lo 59.00 59.00 8.85 8.85 0.00 0.00 0.00
02:56:35 PM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
[pattern continues]
本质上,带宽使用率在 0-8MB/秒之间波动。我们尚未能够找出这种波动的原因。
任何指点/建议都会有很大帮助。
编辑 1:我们将 TCPNODELAY 设置为 true。
编辑 2:Java ParNew GC 在这些机器上每隔一秒运行一次。
编辑3:我们只运行一个 java 进程。
编辑 4:我们正在运行 +XX:+DisableExplicitGC
答案1
我认为这是你的线索:
Java ParNew GC 每隔一秒在这些机器上运行一次。
您的 Java 应用程序通过网络进行通信。每隔一秒,您就会暂停 Java 应用程序以运行垃圾收集。您每隔一秒才会看到网络流量,这意味着应用程序每隔一秒才会运行一次。
看来您的网络流量模式完全符合预期?
运行垃圾收集每两秒当然对你没有帮助。如果 JVM 自己运行这个,那么你需要更大的堆大小。如果你用System.gc()
或来请求这个收集Runtime.gc()
,那么尝试不要那么频繁地请求它,看看流量模式是否遵循 GC 暂停。
深入研究特定应用的垃圾收集问题远远超出了本网站的回答范围,但我建议选择一些对你的应用很重要的指标,并在尝试不同的堆大小、不同的 GC 请求间隔和 JVM 中的不同 GC 时测量该指标。有很多关于使用的文章垃圾猫分析GC性能。
不要太担心暂停频率、暂停次数或暂停长度。使用垃圾收集器和设置,以获得对您的应用程序最有用的最佳指标。
我想你会发现很多 Java 工程师会说根本不要手动请求垃圾收集。JVM 开发人员投入了大量精力来调整 GC,使其自动变得智能。他们比你我这样的凡人知道的更多。相信他们。