Java应用在多核服务器上压力不均衡问题

来源:互联网 发布:西安软件公司软件开发 编辑:程序博客网 时间:2024/06/01 09:36

         这篇blog的问题不能算是解决,仅仅只是一种分析和猜测,后续的一些行动可能会证明一些猜想,也可能什么都解决不了。如果有和我相同情况的同学,也知道是什么问题造成的,请不吝赐教。

问题:

上周周末,没有和同事们出去Outing,在家管孩子,去生产环境观察了一下集群机器的当前运行状态,发现应用在这些多核机器上压力极端不均匀。

         Top一下大致状态如下:

      http://www.flickr.com/photos/33194437@N03/3702676767/(没办法,blog无法上传,引用图片,只好给链接了)

 

         峰值的时候,单CPU的使用率都到了80%,这种情况对于多核服务器来说是很不正常的使用。对于Java的开发者来说,多线程编程是无法控制线程如何在CPU上分配的,因为Java本身不实现线程机制,说是跨平台的语言,但是性能及特性会根据操作系统的实现有很大的差异,因此Java调优有时候需要对系统配置甚至内核作调优。

分析:

         首先在测试环境下作了多次同样的压力测试,尝试了与线上一样的操作系统版本,相似的配置,但测试结果却是负载分配很均匀。

      http://www.flickr.com/photos/33194437@N03/3703485402/  (没办法,blog无法上传,引用图片,只好给链接了) 
     

         此时重新启动了一台问题机器,发现负载降下来了,同时也很均衡,也就是说在当前的压力下不应该有这样高的cpu消耗,同时也排除了硬件或者操作系统的一些配置问题。

         CPU满负荷的情况下,很多时候会认为应该是循环造成的,对于单个CPU的消耗更是。通过Top H查看具体到底哪一个线程会长时间消耗CPU

http://www.flickr.com/photos/33194437@N03/3702676803/ (没办法,blog无法上传,引用图片,只好给链接了) 

 

         可以看到PID13659的线程是“罪魁祸首”,但13659究竟在干什么,是应用的线程还是系统的线程,是否是陷入了死循环,不得而知。接着就按照Java的土办法,Kill -3 pid,然后看看输出日志。

         根据线程号来查找dump出来的日志中nid,发现这个线程是VM Thread,也就是虚拟机线程。(这里作一下转换,将13659转换成为16进制就是0x355b

http://www.flickr.com/photos/33194437@N03/3703479942/(没办法,blog无法上传,引用图片,只好给链接了) 

 

         pstack看了一下这个线程的工作,结果如下:

Thread 2074 (Thread 1846541216 (LWP 13659)):

#0 0x0659fa65 in ObjectSynchronizer::deflate_idle_monitors ()

#1 0x065606e5 in SafepointSynchronize::begin ()

#2 0x06613e83 in VMThread::loop ()

#3 0x06613a6f in VMThread::run ()

#4 0x06506709 in java_start ()

#5 0x00aae3cc in start_thread () from /lib/tls/libpthread.so.0

#6 0x00a1896e in clone () from /lib/tls/libc.so.6

         搜索了一下ObjectSynchronizer::deflate_idle_monitors,发现了sunbug库中有bug关于jdk1.6中由于这个方法导致运行期问题的说法:http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=803cb2d95886bffffffff9a626d3b9b28573?bug_id=6781744

         然后就直接去openjdk官方网站去查找这个类的代码,大致了解一下他的作用,具体的代码链接如下:http://xref.jsecurity.net/openjdk-6/langtools/db/d8b/synchronizer_8cpp-source.html
主要工作应该是对资源对象的回收,在加上pstack的结果,应该大致知道是对线程资源的管理。但具体代码就没有进一步分析了。

接着就分析一下自己的应用:

         压力测试(高强度、长时间)都做过,没有发现什么异常。

         本身应用是否会存在的缺陷导致问题呢。有人说VM Thread兼顾着GC的工作,因此内存泄露,对象长期积压过多也可能影响,但其实在dump的结果可以看到,GC有单独的工作线程,同时我也观察到GC这些线程的工作时间长度,因此由于GC繁忙导致CPU上去,基本上来说可以排除。

         其次在SIP项目中使用了JDK的线程池(ExecutorService)LinkedBlockingQueue。后者以前的文章里面提到在1.5版本里使用poll方法会有内存泄露,到1.6虽然没有内存泄露,但是临时锁对象增长的很快,会导致GC的频度增加。

行动:

         上面零零散散的一些分析,最终让我决定有如下的行动:

1.       升级某一台服务器的JDK,当前是1.6.0_10-b33,打算升级到1.614版本。比较观察多台机器的表现,看是否升级了JDK可以解决问题。

2.       去除LinkedBlockingQueue作为消息队列,直接由生产者将生产结果按照算法分配给消费者线程,避免竞争,锁的消耗,同时也防止LinkedBlockingQueue带来的资源消耗。

3.       测试环境继续作长时间的压力测试,同时可以结合Jprofile之类的工具来分析长时间后可能出现的问题。

后话:

         这年头真的啥都要学一点,求人不如求己。

SA,DBA,测试都需要能够去学习一些,起码在初期排查问题上自己能够做点啥,要不然别人也忙,自己又无从下手。就好比这次压力测试好不容易排上队,但是还是满足不了及时上线的需求,因此自己去LoadRunner压,好歹给出一个零时的报告先大家看着。应用的异常有时候是应用本身设计问题,也可能是开发语言的问题,也可能是操作系统的问题,因此要去定位这种比较复杂的问题,真的需要有耐心去好好的学习各种知识,现在看来知识还是匮乏啊,要不然就可以分析出openjdk中可能存在的问题。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ipad来不了机怎么办 深圳车牌租用怎么办的 电脑连wiwf老掉线怎么办 电脑要设置密码怎么办 苹果笔记本电脑忘记密码怎么办 换了外屏有缝隙怎么办 苹果7屏幕松动怎么办 平板电脑屏幕一直闪怎么办 平板电脑屏幕模糊了怎么办 平板电脑模糊怎么办啊 苹果没有声音了怎么办 微信视频回声怎么办 苹果手机总卡机不动怎么办 苹果手机不掉电怎么办 iphonex屏幕漏液怎么办 苹果6sp充不进电怎么办 iphone6充电越少怎么办 苹果6不能充电怎么办 脸部苹果肌很大怎么办 液晶屏上有划痕怎么办 苹果手机屏幕翘起来怎么办? iphone5s翘屏了怎么办 lpad触屏失灵怎么办 平板一直重启怎么办 苹果平板老死机怎么办 华为屏幕反应慢怎么办 平板屏幕没反应怎么办 iPadmini3触屏了怎么办 联想电脑触摸屏没反应怎么办 电脑触摸屏没反应怎么办 换屏后屏幕乱跳怎么办 联想平板进不去系统怎么办 平板触摸屏坏了怎么办 苹果6触摸不灵敏怎么办 5s home失灵怎么办? 平板触控失灵怎么办 ipad触摸屏坏了怎么办 ipad屏幕颠倒了怎么办 ipad电池坏了怎么办 手机碎屏使屏幕失灵怎么办 电磁炉触屏不灵怎么办