第五章 调优案例分析与实战

5.1 案例分析

5.1.1 高性能硬件上的程序部署策略

      一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU、16GB物理内存,操作系统为64为CentOS5.4,Resin作为web服务器。整个服务器暂时没有部署别的应用,所有硬件资源都可以提供给访问量并不算太大的网站使用。管理员为了尽量利用硬件资源选用了64位的JDK1.5,并通过-Xmx和-Xms参数将Java堆固定在12GB。使用一段时间后发现使用效果并不理想,网站经常不定期出现长时间没有响应的现象。

      监控服务器运行状况后发现网站没有响应是由GC停顿导致的,虚拟机运行在Server模式,默认使用吞吐量优先收集器,回收12GB的堆,一次Full GC的停顿时间高达14秒。并且由于程序设计的关系,访问文档时要把文档从磁盘提取到内存中,导致内存中出现很多由文档序列化产生的大对象,这些 大对象很多都进入了老年代,没有在Minor GC中清理掉。这种情况下即使有12GB的堆,内存也会很快被耗尽,由此导致每个十几分钟出现十几秒的停顿。

      程序部署上的主要问题是过大的堆内存进行回收时带来的长时间的停顿,在高性能硬件上部署程序,目前主要有两种方式:

通过64位JDK来使用大内存;使用若干个32位虚拟机建立逻辑集群来利用硬件资源。

      此案例中的管理员采用了第一种部署方式。对于用户交互性强、对停顿时间敏感的系统,可以给java虚拟机分配超大堆的前提是有把握把应用程序的Full GC频率控制的足够低,至少低到不会影响用户使用,譬如十几个小时乃至一天才出现一次Full GC,这样可以通过在深夜执行定时任务的方式触发Full GC甚至自动重启应用服务器来将内存可用空间保持在一个稳定的水平。

      控制Full GC频率的关键是看应用中绝大多数对象能否符合“朝生夕灭”的原则,即大多数对象的生存时间不应当太长,尤其是不能产生批量的、长生存时间的大对象,这样才能保障老年代空间的稳定。此外,如果读者计划使用64位JDK管理大内存,还需考虑如下几个问题:(内存回收导致的长时间停顿; 现阶段,64位JDK的性能测试结果普遍低于32位JDK; 需要保证程序足够稳定,因为这种应用要是产生堆溢出几乎就无法产生堆转储快照(因为要产生十几GB甚至更大的dump文件),哪怕产生了快照也几乎无法进行分析; 相同的程序在64位JDK中消耗的内存一般比32位JDK大,这是由指针膨胀及数据类型对齐补白等因素导致的。)

      上面的问题听起来有点吓人,所以现阶段不少管理员还是选择第二种方式:使用若干个32位虚拟机建立逻辑集群来利用硬件资源。具体做法是在一台物理机器上启动多个应用服务器进程,给每个服务器进程分配不同的端口,然后在前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。读者不需要太在意均衡器转发所消耗的性能,即使使用64位JDK,许多应用也不止有一台服务器,因此在许多应用中前端的均衡器总是要存在的。

      考虑到在一台物理机器上建立逻辑集群的目的仅仅是尽可能的利用硬件资源,并不需要关心状态保留、热转移之类 高可用性需求,也不需要保证每个虚拟机进程有绝对准确的均衡负载,因此使用无Session复制的亲合式集群是一个相当不错的选择。我们仅仅需要保障集群具备亲和性,也就是均衡器按一定的规则算法将一个固定的用户请求永远分配到固定的一个集群节点进行处理即可,这样程序开发阶段基本不用为集群环境做什么特别的考虑。

       使用逻辑集群会遇到如下问题:尽量避免节点竞争全局的资源;很难最高效率的利用这些资源;各个节点仍然不可避免的受到32位内存限制;大量使用本地缓存的应用,在逻辑集群中会造成较大的内存浪费。

5.1.2 集群间同步导致的内存溢出

       一个基于B/S的MIS系统,硬件为两台2个CPU、8GB内存的HP小型机,服务器是WebLogic9.2,每台机器启动了3个WebLogic实例,构成一个6个节点的亲合式集群,由于是亲合式集群,节点之间没有进行Session同步,但是有一些需求要实现部分数据在各个节点间共享。开始这些数据存放在数据库中,但由于读写频繁竞争很激烈,对性能的影响较大,后面使用JBossCache构建了一个全局缓存。全局缓存启用后,服务正常使用了一个较长的时间,但最近不定期的多次出现内存溢出问题。

      在不出现内存溢出异常的时候,服务内存回收状况一直正常,每次内存回收后都能恢复到一个稳定的可用空间,开始怀疑是程序的某些不正常的代码路径中存在内存泄漏,但管理员反映最近程序并未更新或升级过,也没有进行什么特别的操作。只好让服带着-XX:+HeapDumpOnOutOfMemoryError参数运行了一段时间。在最近一次溢出之后,管理员发回了heapdump文件,发现里面存在着大量的org.jgroups.protocols.pbcast.NAKACK对象。

      JBossCache是基于自家的JGroups进行集群间的数据通信,JGroups使用协议栈的方式来实现收发数据包的各种所需特性的自由组合,数据包接受和发送时要经过每层协议栈的up()和down()方法,其中的NAKACK栈用于保障各个包的有效顺序及重发。

5.1.3 堆外内存导致的溢出错误

5.1.4 外部命令导致系统缓慢

5.1.5 服务器JVM进程崩溃

posted @ 2018-11-06 23:08  strawqqhat  阅读(95)  评论(0编辑  收藏  举报
#home h1{ font-size:45px; } body{ background-image: url("放你的背景图链接"); background-position: initial; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-origin: initial; background-clip: initial; height:100%; width:100%; } #home{ opacity:0.7; } .wall{ position: fixed; top: 0; left: 0; bottom: 0; right: 0; } div#midground{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -1; -webkit-animation: cc 200s linear infinite; -moz-animation: cc 200s linear infinite; -o-animation: cc 200s linear infinite; animation: cc 200s linear infinite; } div#foreground{ background: url("https://i.postimg.cc/z3jZZD1B/foreground.png"); z-index: -2; -webkit-animation: cc 253s linear infinite; -o-animation: cc 253s linear infinite; -moz-animation: cc 253s linear infinite; animation: cc 253s linear infinite; } div#top{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -4; -webkit-animation: da 200s linear infinite; -o-animation: da 200s linear infinite; animation: da 200s linear infinite; } @-webkit-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-o-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-moz-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @keyframes cc { 0%{ background-position: 0 0; } 100%{ background-position: 600% 0; } } @keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-webkit-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-moz-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-ms-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } }