zoukankan      html  css  js  c++  java
  • 【生产环境】Tomcat运行一段时间后访问变慢分析历程

    环境运行一天或者几天,网站访问就很卡,手机端app访问页面出现白屏。Tomcat运行一段时间后访问变慢,但是cpu,内存都正常。日志也是发现不了啥....

    问题的原先分析

    1.环境配置(cpu,内存,使用工具:nmon工具、visualvm工具、jprofiler工具全部用上监控中)

    2.修改info日志,启用error级别日志(待筛选排查)

    3.查看数据库配置连接池(正常)

    4.代码问题对象创建太多(待排查,web里面走拦截器待看)

    5.jvm分配内存太少了(调优,生产环境重启)

    6.并发高了,网站太多人访问(排除)

    7.webapps下面的工程太多了(排除)

    8.数据压力太大数据盘大(排除)

    9.物理机器问题、网络宽度问题...

    Linux环境配置信息

    Tomcat启动行参数的优化

    修改前:

    JAVA_OPTS="-Xmx2048m -Xms1024m -Xmn384M -XX:MaxPermSize=512m -XX:PermSize=128m"
    进行重修调整,修改后:

    JAVA_OPTS="-server -Xmx2048m -Xms2048m -Xmn384M -XX:PermSize=512m -XX:MaxPermSize=512m -Xss512k -XX:+AggressiveOpts -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:-UseGCOverheadLimit -XX:+HeapDumpOnOutOfMemoryError -XX:CMSInitiatingOccupancyFraction=75 -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djava.awt.headless=true "
    参数解释:

    -server :

    tomcat是运行在生产环境中的,这个参数必须上,因为tomcat默认是以一种叫java –client的模式来运行的,server即意味着你的tomcat是以真实的production的模式在运行的,这也就意味着tomcat以server模式运行时将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机制,可以获得更多的负载与吞吐量更等

    -Xmx2048m -Xms2048m

    即JVM内存设置了,把Xms与Xmx两个值设成一样是最优的做法。存放 new MyClass() 的对象,是GC的主要区域,-Xms / -Xmx 分别是堆的初始容量、最大可扩展容量,建议初始值设置为最大值,以免反复扩展或缩减的开销;

    -Xmx2048m:设置JVM最大可用内存为2048M。
    -Xms2048m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

    -Xmn512m

    设置年轻代大小为512m。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

    -XX:PermSize=512m -XX:MaxPermSize=512m

    JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;在数据量的很大的文件导出时,一定要把这两个值设置上,否则会出现内存溢出的错误。由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。那么,如果是物理内存4GB,那么64分之一就是64MB,这就是PermSize默认值,也就是永生代内存初始大小;四分之一是1024MB,这就是MaxPermSize默认大小。

    -Xss512k

    是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程 大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory。

    设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

    -XX:+AggressiveOpts

    作用如其名(aggressive),启用这个参数,则每当JDK版本升级时,你的JVM都会使用最新加入的优化技术(如果有的话)

    -XX:+DisableExplicitGC

    在程序代码中不允许有显示的调用”System.gc()”。看到过有两个极品工程中每次在DAO操作结束时手动调用System.gc()一下,觉得这样做好像能够解决它们的out ofmemory问题一样,付出的代价就是系统响应时间严重降低,就和我在关于Xms,Xmx里的解释的原理一样,这样去调用GC导致系统的JVM大起大落,

    -XX:+UseBiasedLocking

    启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得你的appserver内对线程处理自动进行最优调配。

    -XX:MaxTenuringThreshold=31

    设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。这个值的设置是根据本地的jprofiler监控后得到的一个理想的值,不能一概而论原搬照抄。

    -XX:+UseConcMarkSweepGC

    即CMS gc,这一特性只有jdk1.5即后续版本才具有的功能,它使用的是gc估算触发和heap占用触发。我们知道频频繁的GC会造面JVM的大起大落从而影响到系统的效率,因此使用了CMS GC后可以在GC次数增多的情况下,每次GC的响应时间却很短,比如说使用了CMS GC后经过jprofiler的观察,GC被触发次数非常多,而每次GC耗时仅为几毫秒。

    -XX:+UseParNewGC

    对年轻代采用多线程并行回收,这样收得快。

    -XX:+CMSParallelRemarkEnabled

    在使用UseParNewGC 的情况下, 尽量减少 mark 的时间

    -XX:+UseCMSCompactAtFullCollection

    在使用concurrent gc 的情况下, 防止 memoryfragmention, 对live object 进行整理, 使 memory 碎片减少。

    -XX:LargePageSizeInBytes=128m

    指定 Java heap的分页页面大小

    -XX:+UseFastAccessorMethods

    get,set 方法转成本地代码

    -XX:+UseCMSInitiatingOccupancyOnly

    指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 启动收集

    -XX:CMSInitiatingOccupancyFraction=70

    CMSInitiatingOccupancyFraction,这个参数设置有很大技巧,基本上满足(Xmx-Xmn)(100- CMSInitiatingOccupancyFraction)/100>=Xmn就不会出现promotion failed。在我的应用中Xmx是6000,Xmn是512,那么Xmx-Xmn是5488兆,也就是年老代有5488 兆,CMSInitiatingOccupancyFraction=90说明年老代到90%满的时候开始执行对年老代的并发垃圾回收(CMS),这时还 剩10%的空间是548810%=548兆,所以即使Xmn(也就是年轻代共512兆)里所有对象都搬到年老代里,548兆的空间也足够了,所以只要满 足上面的公式,就不会出现垃圾回收时的promotion failed;

    因此这个参数的设置必须与Xmn关联在一起。

    -XX:-UseGCOverheadLimit

    -XX:+HeapDumpOnOutOfMemoryError

    -XX:CMSInitiatingOccupancyFraction=75

    -XX:CMSFullGCsBeforeCompaction=2

    -XX:SoftRefLRUPolicyMSPerMB=0

    -Djava.awt.headless=true

    这个参数一般我们都是放在最后使用的,这全参数的作用是这样的,有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现。

    -XX:+UseParallelOldGC

    -XX:+PrintGCDateStamps

    -XX:+PrintGCDetails

    -Xloggc:/opt/lucky/app/lucky/tomcat/logs/gc.log

    上述这样的配置,基本上可以达到:系统响应时间增快、JVM回收速度增快同时又不影响系统的响应率、JVM内存最大化利用、线程阻塞情况最小化。

    Tomcat启动慢调整
    JVM环境中解决:

    打开vi $JAVA_HOME/jre/lib/security/java.security这个文件,找到下面的内容:

    securerandom.source=file:/dev/urandom

    替换成

    securerandom.source=file:/dev/./urandom

    代码模块进行

    数据库查询语句进行

    参考:

    JVM调优总结 -Xms -Xmx -Xmn -Xss

    http://unixboy.iteye.com/blog/174173

  • 相关阅读:
    Struts整合Spring3时注意
    Android组件通讯之BroadcastReceiver应用闹钟服务
    Android组件通讯之Pending Intent与Notification
    Android组件通讯之Service的基础绑定
    Android网络编程之Web Service初步(服务器端搭建)
    Android数据存储之ContentProvider调用联系人数据
    Android网络编程之Socket方式上传对象序列化文件(服务器端)
    Android组件通讯之可跨进程的远程Service调用
    Android网络编程之Web Service初步(客户端)
    Android网络编程之Socket方式上传对象序列化文件(客户端)
  • 原文地址:https://www.cnblogs.com/userzf/p/10782169.html
Copyright © 2011-2022 走看看