`
gaozzsoft
  • 浏览: 413265 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Java应用OOM内存过高解决及优化

阅读更多

 JVM OOM优化

 

jmap -heap 30378  

jstat -gcutils 30378 1000 1000  

jmap -histo 30378 | head -20  就可以查看某个应用pid的java服务占用内存排名前20的类

jmap -dump:format=b,file=mydump.hprof 30378 

查看JAVA应用线程情况:ps p 30378 -L -o pcpu,pmem,pid,tid,time,tname,cmd

PS: 30378是JAVA进程ID

ulimit  -a 查看文件句柄 查看进程被限制使用的资源

 

修改文件句柄:

vim /etc/security/limits.conf

# 添加如下的内容

* soft nproc 11000

* hard nproc 11000

* soft nofile 65535

* hard nofile 65535

修改完重启服务器

 

观察fullgc情况 尝试jvm参数修改 尝试修改xmn。建议设置的比例是年青代:年老代为1:2

 

 

 

 

总结一下FGC的原因:

(1) 调用System.gc()时,系统建议执行Full GC,但是不必然执行

(2) 老年代空间不足(老年代空间不足,在不GC就OOM,这其实可能是Major GC会和Full GC混淆使用情况)

(3) 方法区空间不足

(4) 通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5) 由Eden区、survivor space0 (From Space) 区向survivor space1 (To Space)区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小,其实也就是老年代空间不足的情况而已。

 

dump下来jvm日志分析方法:

1.jmap 还有一个指令可以把整个内存情况转成文件形式保存下来,如下:

jmap -dump:format=b,file=mydump.hprof 30378

2.在JVM启动时设置,如果发生OOM,则dump出文件。命令如下:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/mydump.hprof

如果快照文件不大,可以下载到本地,然后通过 MAT 分析,也可以在线分析( https://fastthread.io/ );如果快照文件很大,可以在服务器上直接分析,使用的命令是:

jhat mydump.hprof

3.jvm日志分析-使用jhat命令

jhat也是jdk内置的工具之一。主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言 

例子:jhat mydump.hprof

 

FastDFS优化:

一开始在测试的时候并发达到200,500左右都是很正常的。但是到了线上环境,峰值达到每秒几百个,就受不了,

在上传的时候出现各种异常

java.net,SocketException:Connection closed by remote host,Response:null

 

java.net.SocketException:timeout,Response:null

 

java.io.EOFException,Response:null

 

javax.net.ssl.SSLException:SSL peer shut down incorrectly,Response:null

 

java.io.IOException:recv package size -1 ! = 10

 

 

解放方案:

max_connections=10240 或 65535

 

高并发情况下扩大fastdfs最大连接数,根据服务器情况酌情扩大。

 

fastdfs5.05版本最大连接数256,科大讯飞语音接口,异步方法接收响应,然后在直接处理上传,相当于来了多少请求就会开多少连接,很快就会打满最大连接数,造成后面的上传异常,只有前面的上传完成后,放开了才能获取到服务端的连接,但是异步处理方法不是获取不到就阻塞住的,他是直接new了去上传,然后服务端没有连接线程来处理这个,就会返回一个空的路径或者是连接异常这种错误。

 

我们用fastdfs做为商户文件资料的存储,近期随着业务变动,也开始对外提供文件访问服务,发现请求偶尔会报错,异常大概如下:

java.net.SocketException: Connection reset

 

解决方法:

 

由于fastdfs客户端的实现中,storageClient、trackerServer和storageClient都不是线程安全的,而且,每次调用都会new一个socket连接,

调用完成后会关闭,所以不能复用。

 

在5.05版本中,storage和tracker的默认最大连接数(max_connections)为256,访问量一大就会超出报错,所以要根据场景,适当调整该值的大小。

 

最大并发连接数 max_connections

使用 v5.04 及后续版本,可以根据实际需要将 max_connections 设置为一个较大的数值,比如 10240 或 65535 甚至更大。

 

配置文件:tracker.conf 和 storage.conf 

参数名:max_connections

缺省值:256

 

说明:FastDFS为一个连接分配一个task buffer,为了提升分配效率,FastDFS采用内存池的做法。 

FastDFS老版本直接事先分配 max_connections 个buffer,这个做法显然不是太合理,在 max_connections 设置过大的情况下太浪费内存。

v5.04对预分配采用增量方式,tracker一次预分配 1024个,storage一次预分配256个。

#define ALLOC_CONNECTIONS_ONCE 1024 

总的task buffer初始内存占用情况测算如下

改进前:max_connections * buffer_size

改进后:max_connections和预分配的连接中那个小 * buffer_size 

使用v5.04及后续版本,可以根据实际需要将 max_connections 设置为一个较大的数值,比如 10240 甚至更大。

注意此时需要将一个进程允许打开的最大文件数调大到超过max_connections否则FastDFS server启动 会报错。

vi /etc/security/limits.conf 重启系统生效

*               soft     nofile          65535

*               hard     nofile          65535

 

另外,对于32位系统,请注意使用到的内存不要超过3GB

 

通过 ulimit -a 查看进程被限制使用的资源。

设置句柄的方式(最高只能为65535):

1、临时修改的方法:

ulimit -HSn 65535

此方法当前会话有效

2、永久修改方法(修改单个进程打开的最大句柄数)

修改配置文件的方式:设置最大进程数和最大文件打开数:

vim /etc/security/limits.conf

# 添加如下的内容

* soft nproc 11000

* hard nproc 11000

* soft nofile 65535

* hard nofile 65535

修改完重启服务器

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics