案例分析

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

方案一: 使用通过64位JDK使用大内存
问题:

  • 内存大, GC时间长, 必须把Full GC的频率控制的足够低, 才不会影响用户使用
  • 64位JDK性能差于32位的, 相同的程序在64位中消耗的内存大
  • 堆溢出无法产生快照分析(快照高达十几G)

方案二: 使用若干个32位虚拟机建立逻辑集群来利用硬件资源, 前端负载均衡, 以方向代理的方式来分配用户请求
问题:

  • 需要避免节点竞争全局的资源, 例如同时读写磁盘文件导致IO异常
  • 很难高效率的利用某些连接池
  • 依然受到32位内存限制
  • 各节点的本地缓存造成浪费, 需要改成集中式缓存

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

堆外内存导致的溢出错误

除了java堆和永久代之外, 下面这些区域还会占用较多的内存, 这里内存的总和会受到操作系统进程最大内存的限制:

  • Direct Memory: 可通过-XX: MaxDirectMemorySize调整大小, 内存不足时抛出OOM或OOM: Direct buffer memory
  • 线程堆栈: 可通过-Xss调整大小, 内存不足时抛出SOF(纵向无法分配, 无法建立新的栈帧)或OOM(横向无法分配, 无法建立新的线程)
  • Socket缓存区: 每个Socket连接都有Receive和Send两个缓存区, 分别占37kb和25kb的内存. 如果无法分配会抛出IOException: Too many open files
  • JNI代码
  • 虚拟机和GC

外部命令导致系统缓慢

比如在java代码中调用shell脚本

服务器JVM进程崩溃