【问题标题】:Tomcat GC: two machines with the same settings behave differentlyTomcat GC:具有相同设置的两台机器行为不同
【发布时间】:2016-07-22 20:43:42
【问题描述】:

我有两个配置相同的虚拟服务器(Win 2012R2):64GB 内存和 12 个内核。

每个虚拟服务器都有一个 Tomcat 实例 (8.0.36),它们通过 SimpleTcpCluster 进行集群。

关于 GC,我对两者都使用以下内容:

set JAVA_OPTS=-Xms4g 
set JAVA_OPTS=%JAVA_OPTS% -Xmx4g
set JAVA_OPTS=%JAVA_OPTS% -Xss256k
set JAVA_OPTS=%JAVA_OPTS% -XX:+UseG1GC -XX:MaxGCPauseMillis=2000
set JAVA_OPTS=%JAVA_OPTS% -XX:G1HeapRegionSize=8
set JAVA_OPTS=%JAVA_OPTS% -XX:ParallelGCThreads=8 -XX:ConcGCThreads=4 
set JAVA_OPTS=%JAVA_OPTS% -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

一个 Tomcat 实例的性能非常好,我从来没有看到任何明显的性能下降。我确实看到它经常做GC。这是它产生的示例数据:

2016-07-22T09:55:57.164-0400: 36257.947: [GC pause (G1 Evacuation Pause) (young), 0.0408534 secs]
   [Parallel Time: 11.9 ms, GC Workers: 8]
      [GC Worker Start (ms): Min: 36257947.8, Avg: 36257948.0, Max: 36257948.2, Diff: 0.3]
      [Ext Root Scanning (ms): Min: 0.6, Avg: 1.0, Max: 2.4, Diff: 1.8, Sum: 8.0]
      [Update RS (ms): Min: 0.6, Avg: 1.8, Max: 2.1, Diff: 1.4, Sum: 14.4]
         [Processed Buffers: Min: 11, Avg: 16.3, Max: 21, Diff: 10, Sum: 130]
      [Scan RS (ms): Min: 0.7, Avg: 0.9, Max: 1.0, Diff: 0.2, Sum: 7.3]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.2, Max: 0.3, Diff: 0.3, Sum: 1.2]
      [Object Copy (ms): Min: 7.2, Avg: 7.5, Max: 7.7, Diff: 0.5, Sum: 59.7]
      [Termination (ms): Min: 0.1, Avg: 0.1, Max: 0.1, Diff: 0.0, Sum: 0.9]
         [Termination Attempts: Min: 324, Avg: 360.5, Max: 388, Diff: 64, Sum: 2884]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 1.0]
      [GC Worker Total (ms): Min: 11.4, Avg: 11.6, Max: 11.7, Diff: 0.3, Sum: 92.6]
      [GC Worker End (ms): Min: 36257959.4, Avg: 36257959.5, Max: 36257959.6, Diff: 0.2]
   [Code Root Fixup: 0.3 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.8 ms]
   [Other: 27.8 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 23.0 ms]
      [Ref Enq: 0.2 ms]
      [Redirty Cards: 0.2 ms]
      [Humongous Register: 0.2 ms]
      [Humongous Reclaim: 0.4 ms]
      [Free CSet: 3.0 ms]
   [Eden: 2406.0M(2406.0M)->0.0B(2401.0M) Survivors: 51.0M->56.0M Heap: 2809.2M(4096.0M)->211.6M(4096.0M)]
 [Times: user=0.06 sys=0.00, real=0.06 secs]

但是,另一个 Tomcat 总是显示缓慢。每次缓慢一段时间后,它都会恢复正常性能。这是它在 GC 中生成的示例数据:

2016-07-22T10:03:22.442-0400: 37959.345: [GC pause (G1 Evacuation Pause) (young), 0.1030285 secs]
   [Parallel Time: 50.4 ms, GC Workers: 8]
      [GC Worker Start (ms): Min: 37959345.4, Avg: 37959345.5, Max: 37959345.6, Diff: 0.2]
      [Ext Root Scanning (ms): Min: 0.4, Avg: 1.2, Max: 5.2, Diff: 4.8, Sum: 9.8]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.1, Avg: 0.4, Max: 0.5, Diff: 0.4, Sum: 3.2]
      [Code Root Scanning (ms): Min: 0.0, Avg: 7.5, Max: 15.1, Diff: 15.1, Sum: 59.6]
      [Object Copy (ms): Min: 33.6, Avg: 40.6, Max: 48.2, Diff: 14.6, Sum: 325.1]
      [Termination (ms): Min: 0.0, Avg: 0.3, Max: 0.4, Diff: 0.4, Sum: 2.3]
         [Termination Attempts: Min: 1, Avg: 880.9, Max: 1086, Diff: 1085, Sum: 7047]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.1, Sum: 0.9]
      [GC Worker Total (ms): Min: 50.0, Avg: 50.1, Max: 50.3, Diff: 0.3, Sum: 400.8]
      [GC Worker End (ms): Min: 37959395.5, Avg: 37959395.6, Max: 37959395.6, Diff: 0.1]
   [Code Root Fixup: 8.7 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.8 ms]
   [Other: 43.1 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 36.5 ms]
      [Ref Enq: 1.2 ms]
      [Redirty Cards: 0.2 ms]
      [Humongous Register: 0.1 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 4.3 ms]
   [Eden: 2300.0M(2300.0M)->0.0B(2346.0M) Survivors: 157.0M->111.0M Heap: 2496.5M(4096.0M)->150.5M(4096.0M)]
 [Times: user=0.42 sys=0.00, real=0.11 secs]

造成这种性能差异的原因可能是什么?我真的不知道从哪里开始。如果您需要有关系统的任何信息,请随时询问。

问候。

更新

这里有更多系统信息:

  • 两个实例都运行同一个面向公众的网站(完全相同的代码)。
  • 两个实例前面有一个 Kemp 负载平衡器。方法是圆的 知更鸟。
  • 相同的 Java 版本:1.8.0.92(再次验证)
  • 两个实例上的负载应该非常相似。
  • 网站不在云端。
  • 这是一个新推出的低流量网站。任何时候平均有 10 - 20 名访客。在如此低的流量下,仍然会出现缓慢的情况。
  • 两个 Tomcat 实例位于两个盒子上。
  • 在装有慢速 Tomcat 实例的盒子上,我有一个被动 SQL Server 2014 实例,它与另一个快速 Tomcat 实例所在的盒子上的主动 SQL Server 2014 实例集群在一起。
  • 两个盒子之间的通信是10G。

【问题讨论】:

  • 它们是否服务于不同类型的流量?工作分配是否均匀?您需要首先验证他们是否都被赋予了相同数量的工作。没有工作负载上下文,GC 和性能信息毫无意义。 140 的心率和 220/110 的 BP 是一个严重的问题,直到您发现受试者正在参加马拉松比赛。
  • 只是一些想法,希望他们都使用完全相同的java版本?他们负载均衡吗?如果是,是不是一个比另一个承受更多的负载?
  • Jim 和 Isiva,非常感谢您的参与!我用其他系统信息更新了帖子。再次感谢!
  • 很难从一个 GC 条目中说是否存在差异 (refproc)。您可以比较“-XX:+PrintFlagsFinal”设置。当 tomcat 终止时,机器是否显示相同的 ram-free 和 swap 使用数?使用气球吗?主机上的不同内存预留?
  • eckes,感谢您的提问。如果我使用“-XX:+PrintFlagsFinal”,我能得到回答你所有问题的数据吗?

标签: java tomcat garbage-collection


【解决方案1】:

当您使用虚拟机时,很可能存在运行在相同硬件容量上的“邻居”。这些邻居可能会从您的虚拟机中窃取容量。例如,在 Amazon 中,如果资源分配冲突,首先优先考虑更大的实例(与 t1.micro 相比,c4.xlarge 将首先获得资源,因此在 t1.micro 中您会看到steal time at top 实用程序)。在我的实践中,当我遇到类似情况时,我会停止并启动慢速实例,然后它会移动到另一个硬件。如果这一次,“邻居”是幸运的,那么窃取时间将不存在(它适用于亚马逊,但我想它适用于其他虚拟机管理程序)。您使用的是什么提供商?

【讨论】:

  • valch85,非常感谢您分享您的想法。我用新的系统信息更新了帖子。再次感谢!
【解决方案2】:

我想说两件事来回答你的担忧:

  • 我不认为您正在经历减速;我们说的是 0.06 对 0.11 秒; EdenSurvivors 之间的细分表明这是 2 个不同的集合。一个清除了伊甸园和幸存者,而另一个清除了伊甸园,但将一些对象提升为幸存者(幸存者的大小在第一次收集中被 GC 增加)。也许提升比内存清理更快...

  • 你这样写:

    两个实例的负载应该非常相似。

...但是你怎么能确定呢?除非您可以触发一对相同的请求(负载均衡器将一个给第一个实例,另一个给第二个实例),否则您无法确定。

整个堆栈的活力以及客户端和服务器的行为都会有所不同。正如您所说的那样,该网站的流量较小,因此平均效果越小,差异可能越大。

微观层面的小局部波动可能会有很大差异,因此一个快照 GC 可以证明这一点,而在宏观层面上,微小的变化最终会导致需要清理的不同事物。

【讨论】:

  • 非常感谢您帮助我!您希望我对系统进行任何更改吗?关于慢速服务器,加载特定页面需要 21 秒。它不断地表现出这种缓慢。对于同一页面,另一台服务器的响应几乎总是即时的。再次感谢您的帮助!
  • 两个服务器是否都在联系活动的 SQL Server 实例?我认为可以肯定的是,图片很大且不完整。继续探索,查看系统日志,任务管理器中的资源利用率......有很多途径可以探索
  • 是的,两台服务器都指向活动的 SQL Server 实例。感谢您的建议!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 2019-07-04
相关资源
最近更新 更多