高并发环境下系统宕机案例分析

在性能测试的时候,当并发数达到200时触发该问题

现象表现为,load达到200左右,CPU高达100%,内存使用正常,FullGC频率为1小时一次。虽然java进程正常,jvm并未崩溃,但是系统已经拒绝服务,可视为宕机。

该问题一直持续到第二天上班时。在发现问题后,我们停止了LoadRunner,同时也停止了apache,也就是可以保证系统不再接收任何请求。

可是系统并未因此恢复正常。经分析怀疑系统存在死循环之类耗CPU的操作。

通过top shift+h shift+p  命令,查看线程情况,发现出现上百个java线程,他们各占1%的cpu。

进一步确定是代码问题造成的本次故障。

通过jstack命令打印出java线程的快照到日志文件,对日志文件进行分析,发现大多java线程的快照如下

扫描二维码关注公众号,回复: 667304 查看本文章

 

"http-bio-8080-exec-2957" daemon prio=10 tid=0x09d01800 nid=0x4841 runnable [0x69fd4000]
java.lang.Thread.State: RUNNABLE
at org.apache.commons.collections.map.AbstractHashedMap.getEntry(AbstractHashedMap.java:440)
at org.apache.commons.collections.map.LRUMap.get(LRUMap.java:174)
at com.hongli.pandora.item.manager.WeightScoreComputor.compute(WeightScoreComputor.java:29)
at com.hongli.pandora.item.manager.CargoManager$2.compare(CargoManager.java:462)
at com.hongli.pandora.item.manager.CargoManager$2.compare(CargoManager.java:458)
at java.util.Arrays.mergeSort(Arrays.java:1270)


因此确定apache的LRUMap存在问题,经过对代码的分析发现,LRUMap是线程不安全的,在高并发的环境下,触发了死循环的bug。

最终通过在WeightScoreComputor中加入ReentrantReadWriteLock来手动保证线程的安全的方式解决了这一问题。


总结:高并发环境下暴露出的问题通常是由于内存泄漏,线程不安全等问题导致,除了在编码期间充分考虑这些问题外,更重要的是要进行充分的压力测试,并且对发生的问题进行合理的分析和排查,以解决问题和避免类似问题的再现。

这是一例典型的线程不安全的bug导致系统宕机的案例,再次提醒我们在编码过程中,必须时刻牢记共享变量的危险性,应尽量避免使用共享变量,在必须使用的情况下,必须保证共享变量在多线程环境下的安全性。

猜你喜欢

转载自woodbird456.iteye.com/blog/1682111