配色: 字号:
合理配置RESIN内存
2013-07-16 | 阅:  转:  |  分享 
  
合理配置RESIN内存-java.lang.OutOfMemoryError:PermGenspace及其解决方法2013-01-1115:50:53

分类:Java

[开发]resin+spring+struts配搭在线上常见的三个问题



郑昀?201102

1、文件句柄数问题

现象1:访问页面出现500错误,错误描述为:java.lang.NoClassDefFoundError,后面跟的类名各式各样不一一列举了。

现象2:Resin被Wathcdog自动重启,日志中表明这是因为:Resinshutdownfromoutoffiledescriptors。

分析:由于Linux默认文件句柄限制为1024(通过命令ulimit–n来查看),所以当WebServer应对高负载起了大量线程,incomingsocketconnections和outgoingsocketconnections都很多,而且后台代码也可能涉及大量句柄打开,尤其是struts+spring组合。

因此当句柄数迅速到达1024的限制后,无法打开新句柄,于是乎文件打不开、类定义找不到,诸如此类的错误就出现了。

解决:

短期策略是调大Linux下对文件句柄数限制。操作如附录1所示。对于这个数字,一般建议是32667,也可以设置的更大,我们直接调为51200。

?

2、PermSize问题

现象:Resin被持续访问一段时间后,比如一天,就会报告如下500错误,导致所有页面不能访问:

???OutOfMemoryError:PermGenspace

此时,就只能重启机器了,重启resin都没用。

分析:因为线上用了spring+struts,这些框架用到大量动态class,ClassLoader是把这部分内存放在PermGenspace里的。而JVM的GC是不会清理PermGenspace的。这样很容易导致线上应用报告PermGenspace内存溢出。

解决:通过在resin.xml中增加jvm-arg一系列参数,调大“PermSize”和“MaxPermSize”这两个参数来尽量避免出现JVM内存永久保存区域溢出错误。PermSize默认值参考附录2。修改情况参见附录3。

?

3、Xmx和Xms问题

现象:Resin报告如下500错误,导致所有页面不能访问:

???OutOfMemoryError:Javaheapspace

此时重启resin还可以恢复。

分析:JVM默认的最大可用内存(-Xmx参数)和初始堆大小(-Xms参数)都偏小,很容易限制住服务器的能力。当Java架构的能力还没有发挥出来时,就已经被系统默认的各种参数限制住了,导致各种各样的异常。

解决:通过在resin.xml中增加jvm-arg一系列参数,调大“Xms”和“Xmx”以及“Xmn”这三个参数。修改情况参见附录3。Xmn附录4。

其中Xmx的值可以设置得很大,比如4096MB,跟你的物理内存大小差不太多都行,64位Linux支持得住。Xmn的值是Xmx数值的1/4。

Xms的值可以与Xmx一样,省得当压力上来后,初始堆大小发现不够,JVM又得花时间去把内存区大小扩到最大可用内存的数值,就在这个过程,持续不断的高负载可能已经将服务器冲垮。这个机理就类似于我们熟知的SQLServer要根据业务,仔细思考指定数据库空间初始值和最大值以及自增长模式。默认SQLServer数据库空间自动增长是按10%比例增加的:如果你最开始建库时分配了1GB空间,但当压力上来后,数据很快到达1GB,那么数据库就会先锁住所有请求,自动在磁盘上增长出100MB的空间,在这个自动增长过程,所有Web请求就会被挂住,最终可能全部超时。

?

附录附录1:

编辑/etc/profile,加入

ulimit-n51200

有人认为设置为4096就可以,但在网络服务器上此数字最好调成几万,不然流量冲上来太容易冲破。

还有设置命令是:ulimit?–SHn51200,-S、-H这两个参数的说明如下:

-H设置硬件资源限制。

-S设置软件资源限制。

-nsize:设置内核可以同时打开的文件描述符的最大值。

还有另一种操作修改三个地方的设置,参见《修改Ubuntuulimit限制》。

?

附录2:

没有给resin.xml加PermSize的情况下,默认计算规则是:

“JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。”

那么,如果是物理内存4GB,那么64分之一就是64MB,这就是PermSize默认值,也就是永生代内存初始大小;

四分之一是1024MB,这就是MaxPermSize默认大小。

?

附录3:

优化规则:Server端的JVM最好将-Xms和-Xmx设为相同值。为了优化GC,最好让-Xmn值约等于-Xmx的1/4。

线上resin4.0.15的resin.xml中增加如下配置节点:



???-Xms4096m

???-Xmx4096m

???-Xmn1024m

???-XX:PermSize=128m

-XX:MaxPermSize=256m

???1024

???30s

???512

???60s



?

附录4:

JVM的-Xmn参数含义是YoungGeneration的heapsize。

JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young区升级为Older区。Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能。

献花(0)
+1
(本文系忧郁_小刚首藏)