java web服务器cpu占用太高的处理

平时项目中有时遇到cpu太高的状况,在此基于本身有限的经验写个分享,此处的服务器都是基于linux平台。html

cpu的占有线程类型总的来讲分为两种:
us :用户空间占用CPU百分比
sy :内核空间占用CPU百分比
在linux下能够经过top命令查看详细,示例以下:linux

 

通常来说CPU us高的解决方法:
CPU us 高的缘由主要是执行线程不须要任何挂起动做,且一直执行,致使CPU 没有机会去调度执行其余的线程。
CPU sy高的解决方法:
CPU sy 高的缘由主要是线程的运行状态要常常切换,对于这种状况,常见的一种优化方法是减小线程数数据库

 

我平时具体的步骤以下:缓存

1.获得线程最高的几个id(ps- process state)服务器

ps  -eLo pid,lwp,pcpu | grep  15285|sort -nk 3   网络

 

2.导出JAVA线程栈信息异步

命令:kill -3 [PID] 或者 jstackjvm

 

3.从栈信息中找到线程数多的几个socket

命令:sort  文件名 | uniq -c | sort -nk 1优化

 

4.分别分析线程数最多的前十个线程和线程占用cpu最高的前10个线程

      这步是最关键的,找出这些异常点,好比某个业务功能点占用较高的cpu或者某种类型的线程数量比较多,这个和业务以及具体程序紧密关联的,在此就很少说了。

 

5.分析占用cpu最高的前10个线程,结果示例以下:

0x1a5:gc线程
" Concurrent Mark-Sweep GC Thread#0" prio=1 tid=0x0000002b29df1400 nid= 0x1a5 runnable 
0x35f:memcache线程
"memcache5-CacheThread" prio=1 tid=0x0000002b3d277de0 nid= 0x35f runnable [0x0000000042755000..0x0000000042755c30]
0x35e:memcache线程
"memcache1-CacheThread" prio=1 tid=0x0000002b371212f0 nid=0x35e runnable [0x0000000042654000..0x0000000042654cb0]
0x14e9:RMI线程
" RMI TCP Connection(102)-10.23.241.59" daemon prio=1 tid=0x0000002b37e72790 nid=0x14e9 runnable [0x000000005103c000..0x000000005103deb0]
0x1be:memcache线程
"memcache5-CacheThread" prio=1 tid=0x0000002b3dba4790 nid=0x1be runnable [0x0000000041a48000..0x0000000041a48eb0]
0x1bd:memcache线程
" memcache1-CacheThread" prio=1 tid=0x0000002b3fb70340 nid=0x1bd runnable [0x0000000041947000..0x0000000041947b30]
0x1af:jdk编译线程
"CompilerThread1" daemon prio=1 tid=0x0000002b30e11620 nid=0x1af waiting on condition [0x0000000000000000..0x000000004123f7c0]
0x1ae:jdk编译线程
"CompilerThread0" daemon prio=1 tid=0x0000002b30e10280 nid=0x1ae waiting on condition [0x0000000000000000..0x000000004113e440]
0x1684:http请求线程,经过该线程栈能够看到此处调用的是hibernate查询
" http-8080-Processor123" daemon prio=1 tid=0x0000002b37dfd9d0 nid=0x1684 runnable [0x000000005afd7000..0x000000005afdcd30]
 
--------------------------------------------------------------------------------------------------------------------------------

 6.系统优化

      若是找出了哪些功能点占用cpu高,接下来就须要优化了,能够从业务和技术手段两方面来进行,平时工做中比较经常使用的技术手段:

      弹性时间:对高使用率的请求分散到不一样的时间,好比采用队列或异步,减小同一时间处理的请求

      批处理或定时任务:把请求组合成批,这样可使得时间真真的都有效的用在了处理上,而不是网络传输等准备工做上。(减小网络传输、数据库链接、socket链接)

      缓存:结果缓存起来,空间换时间

  --------------------------------------------------------------------------------------------------------------------------------

 

7.若是是gc线程比较费时,则须要进一步的定位:

      首先查看一下gc策略是否合理,而后用命令jmap -F -dump:live,file=jmap.hprof [PID] 导出内存dump文件,我通常每隔5s导一次,一共导出3次。用Eclipse Memory Analyzer分析导出来的文件,分析是哪一个类占用内存比较多,分析出可能存在内存泄露的地方。

      注意jvm分配内存时一个大对象的分配比多个小对象的分配效率要低,若是对象比较大,进行拆分能提升效率,具体缘由以下:

      Java对象所占用的内存主要从堆上进行分配,堆是全部线程共享的,所以在堆上分配内存时须要进行加锁,这致使了建立对象开销比较大。当堆上空间不足时,会触发GC,若是GC后空间仍然不足,则抛出OutOfMemory错误信息。Sun JDK为了提高内存分配的效率,会为每一个新建立的线程在新生代的Eden Space上分配一块独立的空间,这块空间称为TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行状况计算而得,可经过-XX:TLABWasteTargetPercent来设置TLAB可占用的Eden Space的百分比,默认值为1%。JVM将根据这个比率、线程数量及线程是否频繁分配对象来给每一个线程分配合适大小的TLAB空间 。在TLAB上分配内存时不须要加锁,所以JVM在给线程中的对象分配内存时会尽可能在TLAB上分配,若是对象过大或TLAB空间已用完,则仍然在堆上进行分配,所以在编写Java程序时,一般多个小的对象比大的对象分配起来更加高效

 

http://hi.baidu.com/i1see1you/blog/item/6438aecac4dd959bc917683d.html

相关文章
相关标签/搜索