一个线上的tomcat服务,只提供了一个查询接口。经常在早上访问量最大的时候,出现查询越来越慢,重启后可以回复的情况。
为了彻底查清楚问题,整理了一下思路。
1.首先检查服务器的CPU、内存占用没有异常。
2.考虑是高并发带来的影响,在测试服务上模拟调用。
模拟调用
一、在linux系统中安装wrx,参考:
wrk压力测试使用心得(详细)_小宇的博客-CSDN博客_wrk
Linux下性能压测工具WRK的使用_白清羽的博客-CSDN博客
注: xml参数需要用 [[ ]]包裹起来,如果xml中还包含xml参数需要把<>用转义符代替。
编写语句开始并发测试:
wrk -t10 -c100 -d300s -T3s --latency -s /home/wrk/param.lua http://192.168.7.204:8094/reportquery/services/soap
发现高并发情况下,查询时间从 50ms,增加到了1-2s。
二、监测tomcat运行状态
通过启动java自带的检测工具 jvisualvm 进行检测。有时候在java目录下打开会看不到运行的tomcat,可以通过cmd命令行里 启动jvisualvm。
通过 “线程dump”检查线程池日志,发现了两个问题。
第一个问题如下
"http-nio-8094-exec-41" #80 daemon prio=5 os_prio=0 tid=0x000000002606b800 nid=0x1834 runnable [0x00000000378fc000]
java.lang.Thread.State: RUNNABLE
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at com.thoughtworks.xstream.XStream.registerConverterDynamically(XStream.java:1130)
at com.thoughtworks.xstream.XStream.setupConverters(XStream.java:1028)
at com.thoughtworks.xstream.XStream.<init>(XStream.java:592)
at com.thoughtworks.xstream.XStream.<init>(XStream.java:514)
at com.thoughtworks.xstream.XStream.<init>(XStream.java:483)
at com.thoughtworks.xstream.XStream.<init>(XStream.java:429)
at com.thoughtworks.xstream.XStream.<init>(XStream.java:396)
at com.tsmti.sys.util.XmlCoverUtil.toBean(XmlCoverUtil.java:48)
at com.tsmti.sys.lisservice.LabServiceImpl.lisReportQuery(LabServiceImpl.java:84)
at com.tsmti.sys.lisservice.LabServiceImpl.invoke(LabServiceImpl.java:49)
at com.tsmti.sys.lisservice.LabServiceImpl$$FastClassBySpringCGLIB$$c6a4237e.invoke(<generated>)
当并发数增加时,xstream反序列化进程打服增加,通过优化xstream的调用方式,解决了。
修改前:
public static <T> T toBean(String xmlStr, Class<T> cls) {
//注意:不是new Xstream(); 否则报错:java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserFactory
XStream xstream = new XStream(new DomDriver());
xstream.ignoreUnknownElements();
xstream.processAnnotations(cls);
T obj = (T) xstream.fromXML(xmlStr);
return obj;
}
修改后:
private static final ConcurrentHashMap xStream = new ConcurrentHashMap<String, XStream>();
private static XStream getXStream(Class<?> objName) {
String key = objName.getName();
if (xStream.get(key) == null) {
XStream xstream = new XStream(new DomDriver());
xstream.ignoreUnknownElements();
xStream.put(key, xstream);
}
return (XStream) xStream.get(key);
}
/**
* 反序列化
* @param clazz
* @param xml
* @param <T>
* @return
*/
public static <T> T toBean( String xml,Class<T> clazz) {
XStream xStream = getXStream(clazz);
xStream.processAnnotations(clazz);
@SuppressWarnings("unchecked")
T t = (T) xStream.fromXML(xml);
return t;
}
参考:XStream在高并发情况下出现的性能问题_一缕南风的博客-CSDN博客_xstream 性能
第二个问题
当并发量进一步提高后,还是有卡顿,查询 线程dump发现是log4j的问题,通过升级log4j从1.2到2.1解决。