1、高性能硬件上的程序部署策略
服务运行一段时间后发现,网站会出现长时间的卡顿,
分析原因:一次Full GC要用14s的时间,网站会加载大文件到内存中,这些大对象直接进入老年代
没有在Minor GC中清理掉,即使有12G的内存,依然会被很快占用完
如果使用64位JDK 使用高内存配置需要考虑的问题
1、较长的内存回收时间导致的卡顿
2、需要保证程序足够稳定,否则无法生成并分析dump文件
3、相同的程序64位JDK比32位JDK消耗的内存大
解决方案:多部署几个较低配置的服务并使用nginx代理(基本可以解决问题)
此方案的缺点:
连接池,缓存难以共享,需要消耗更多的资源
2、集群间同步导致的内存溢出
3、堆外内存导致的内存溢出
堆外内存值jvm直接使用的操作系统的内存,这部分内存叫做堆外内存,
情况描述:应用程序莫名抛出内存溢出异常,而通过jstat观察内存情况发现一切正常,则此时很可能就是堆外内存溢出
堆外内存的回收策略:在垃圾回收器回收老年代内存时,即发生FullGC的时候会"顺便"回收堆外内存,
但是每个应用程序管理的内存是有限的,
所以,堆外内存和虚拟机的堆栈等内存是此消彼长的关系
堆外内存不会在该区域内存使用完时通知垃圾回收器回收垃圾,
而只是调用System.gc(),如果此时垃圾回收器
依然没有回收该区域的内存,那么就会抛出内存溢出
可以通过使用NIO申请堆外内存即直接内存(Direct Memory)
使用内存较大的区域:
1、通过NIO申请的堆外内存
2、线程堆栈 通过-Xss参数控制
3、Socket缓冲区(Receive和send)
4、外部命令导致系统缓慢
java使用RunTIme.getRunTime().exec()创建外部进程时开销特别大,
这个命令的执行过程是:首先虚拟机克隆一个和当前虚拟机拥有一样环境变量的虚拟机,
再使用这个克隆的虚拟机执行外部命令
然后再关闭克隆的这个虚拟机
5、服务器JVM进程崩溃
情况描述:
通过系统调用另外一个系统的服务,此时是长连接,但是另一个系统的服务返回时间较长,在这个过程中连接关闭,
由于外部系统的服务速度跟不上导致过多的线程和Socket连接太多最终jvm崩溃
解决方案:把外部系统的调用改为消息队列/进程之间的观察者模式