在服务器发生反弹后,大约 40-45 天后,我们会收到连续的“已提交虚拟内存”警报,这表明交换空间的使用量已超过 4GB。这也会导致应用程序运行非常缓慢,并出现大量停滞的交易。服务器设置:
4 个 Tomcat 服务器(版本 7.0.22),由 2 个 Apache 服务器进行负载平衡(而非集群)。Apache 服务器本身为这 4 个 tomcat 服务器提供静态内容和路由。
Java 运行时版本:java 版本“1.6.0_30”Java(TM) SE 运行时环境(build 1.6.0_30-b12)Java HotSpot(TM) 64 位服务器 VM(build 20.5-b03,混合模式
内存启动参数:
MEMORY_OPTIONS="-Xms1024m -Xmx1024m -Xss192k -XX:MaxGCPauseMillis=500 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxPermSize=256m -XX:+CMSClassUnloadingEnabled"
监控——所有生产服务器均提供 Wily 监控,可监控关键服务器参数并根据预定义的设置发送可配置的警报电子邮件。
注意:每台服务器还有另外两个单独的 tomcat 域,运行不同的应用程序
调查区域:
- 没有堆内存泄漏,并且 GC 在任何时间段内都运行良好,没有任何问题
- 当前繁忙的线程数与应用程序使用情况直接相关 - 周末和晚上的线程数比工作时间少
- ThreadLocal 内部使用弱引用。如果 ThreadLocal 没有被强引用,它将被垃圾回收,即使各个线程都通过该 ThreadLocal 存储了值。
- 此外,ThreadLocal 值实际上存储在线程中;如果一个线程死亡,则会通过 ThreadLocal 收集与该线程关联的所有值。
- 如果您将 ThreadLocal 作为最终类成员,则这是一个强引用,并且只有在卸载类后才能回收它。但任何类成员都是这样工作的,因此不被视为内存泄漏。
- 上述问题仅在 ThreadLocal 中存储的值强引用该 ThreadLocal(类似循环引用)时才会出现。在本例中,该值(SimpleDateFormat)没有对 ThreadLocal 的反向引用。此代码中没有内存泄漏。
谁能告诉我这可能是什么原因造成的以及需要监控什么?