在高性能硬件上部署程序,目前有两周形式:

  • 通过64位JDK来应用大内存
  • 应用若干个32位虚拟机建设逻辑集群来利用硬件资源

应用64位JDK治理内存

堆内存变大后,尽管垃圾回收的频率缩小了,但每次垃圾回收的工夫变长了。如果堆内存为14G,那么每次Full GC将长达数十秒。如果Full GC频繁产生,那么对于一个网站是无法忍受的。
对于用户交互性强、对进展工夫敏感的零碎,能够给Java虚拟机调配超大堆的前提是有把握把应用程序的Full GC频率管制的足够低,至多要低到不印象用户应用。
可能面临的问题:

  • 内存回收导致长时间的进展
  • 现阶段,64位JDK的性能广泛比32位JDK低
  • 须要保障程序足够稳固,因为这种利用要是产生堆溢出简直就无奈产生堆转储快照(因为要生产超过10GB的dump文件),哪怕生产了快照也无奈剖析。
  • 雷同程序在64位JDK耗费内存个别比32位JDK大,这是因为指针收缩,以及数据类型对齐补白等因素导致的。

应用32位JVM建设逻辑集群

在一台物理机上启动多个应用服务器过程,每个服务器过程调配不同端口,而后再前端搭建一个负载均衡器,以反向代理的形式来调配拜访申请。
思考在一台物理机器上建设逻辑集群的目标仅仅是为了尽可能的利用硬件资源,并不需要关怀状态保留、热转移之类的高可用性能需要,也不须要保障每个虚拟机过程有相对的负载平衡,因而应用无Session复制的亲合式集群是一个不错的抉择,也不须要保障每一个虚拟机过程有相对的负载平衡,因而应用无Session复制的亲合式集群是一个不错的抉择。咱们仅仅须要保障集群具备亲合性,也就是均衡器按肯定的规定算法(个别依据SessionID调配)将一个固定的用户申请永远调配到固定的一个集群节点解决即可。
肯能遇到的问题:

  • 尽量避免节点竞争部分资源,如磁盘竞争,各节点如果同时拜访某个磁盘文件的话,很可能导致IO异样
  • 很难高效的利用资源池,如连接池,个别都是在节点简历本人独立的连接池,这样有可能导致一些节点池满了而另外一些节点仍有较多空余;
  • 各节点受到32位的内存限度
  • 大量应用本地缓存的利用,在逻辑集群中会造成较大的内存节约,因为每一个逻辑节点都有一份缓存,这时候能够思考把本地缓存改成集中式缓存。

调优案例剖析与实际

场景形容

一个小型零碎,应用32位JDK,4G内存,测试期间发现服务端不定时的抛出内存溢出异样。退出-XX:+HeapDumpOnOutOfMemoryError(增加这个参数后,堆内存溢出就会输入异样日志),但再次发生溢出时,没有相干日志生成。

剖析

在32位JDK上,1.6G调配给堆,还有一部分调配给JVM的其余内存,间接内存最大也只能在残余的0.4G空间中分出一部分,如果应用了NIO,JVM会在JVM内存之外分配内存空间,那么就要小心“间接内存”有余时产生内存溢出异样了。

间接内存的回收过程

间接内存尽管不是JVM内存空间,但它的垃圾回收也由JVM负责。
垃圾收集进行时,虚拟机尽管会对间接内存进行回收,然而间接内存却不能像新生代、老年代那样,发现空间有余了就告诉垃圾收集器进行垃圾回收,它只能等老年代满了后Full GC,而后“顺便”帮它清理掉内存的废除对象。否则只能始终等到抛出内存溢出异样时,先catch掉,再在catch块里调用System.gc()。要是虚拟机还是不听,那就只能眼睁睁看着堆中还有许多闲暇内存,本人却不得不抛出内存溢出异样了。