Tomcat性能测试诊断分析与优化.docx
《Tomcat性能测试诊断分析与优化.docx》由会员分享,可在线阅读,更多相关《Tomcat性能测试诊断分析与优化.docx(28页珍藏版)》请在冰点文库上搜索。
Tomcat性能测试诊断分析与优化
7.2Tomcat性能监控分析
Tomcat是一个免费的开放源代码的Web应用服务器软件,同时Tomcat也是目前世界上用量最大的Java服务器软件之一,主要用来支持运行JavaServlet/JSP。
Tomcat很受广大程序员的喜欢,因为它运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能;而且它还在不断的改进和完善中,任何一个感兴趣的程序员都可以更改它或在其中加入新的功能。
Tomcat的架构图如图7.2所示:
图7.2Tomcat架构图
7.2.1Tomcat性能监控方法
下面介绍几种监控Tomcat性能的方法:
1、Tomcat自带的监控页面
Tomcat附带了一个监控页面,可以查看Tomcat的JVM等状态信息。
但是在访问该页面之前需要先修改配置文件(\conf目录下的tomcat-users.xml文件),添加监控权限。
以Tomcat7.0为例,需要添加一个名为“manager-gui”的角色,再添加用户,例如:
之后访问http:
//192.168.1.101:
8080/manager/status页面,输入monitor账号即可查看Tomcat性能情况,如图7.3所示:
图7.3Tomcat的Status监控页面
2、用LambdaProbe监控Tomcat
LambdaProbe是一款强大的免费开源工具,LambdaProbe拥有几乎所有TomcatManager的功能,可以说是一个增强版本的TomcatManager。
除此之外,TomcatProbe还拥有很多让开发者和系统管理者更方便的功能,从而使得Tomcat对开发者和管理者更加透明,包括:
应用程序,数据源,发布,日志,线程,集群,系统信息,状态,连接器状态等功能。
读者可从以下地址下载probe.1.7b.zip文件:
http:
//www.lambdaprobe.org/d/index.htm
解压probe.1.7b.zip文件,把probe.war部署到Tomcat服务器,修改tomcat-users.xml文件,添加manager账户:
然后访问probe页面即可查看Tomcat相关性能数据,在Connectorstats页面还可以看到图表显示的连接状况,如图7.4所示:
图7.4LambdaProbe监控页面
3、LoadRunner编写脚本实现Tomcat监控
LoadRunner不支持直接监视Tomcat,下面方法采用编写VuGen脚本访问Tomcat的Status页面的方式获取性能数据(利用了关联和lr_user_data_point函数),具体步骤如下:
(1)、首先确保Tomcat中创建了必要权限的用户(编辑Tomcat的\conf目录下的tomcat-users.xml文件),然后在LoadRunner中编写如下脚本:
doubleatof(constchar*string);
externchar*strtok(char*token,constchar*delimiter);
CollectMetrics()
{
intcountP,countS,countF,countR,countK;
intnumValues;
staticintloggedVersionInfo=FALSE;
lr_save_string("127.0.0.1:
8080","ServerName");
web_set_max_html_param_len("65536");
web_set_user("admin",
"admin",
"{ServerName}");
lr_start_transaction("monitortomcat");
web_reg_save_param("JVMFreeMemory",
"LB=Freememory:
",
"RB=MB",
"Ord=1",
LAST);
web_reg_save_param("JVMTotalMemory",
"LB=Totalmemory:
",
"RB=MB",
"Ord=1",
LAST);
web_reg_save_param("JVMMaxMemory",
"LB=Maxmemory:
",
"RB=MB",
"Ord=1",
LAST);
web_reg_save_param("HTTPMaxThreads",
"LB=Maxthreads:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPMinSpareThreads",
"LB=Minsparethreads:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPMaxSpareThreads",
"LB=Maxsparethreads:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPCurrentSpareThreads",
"LB=Currentthreadcount:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPCurrentThreadBusy",
"LB=Currentthreadbusy:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPMaxProcessingTime",
"LB=Maxprocessingtime:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPRequestCount",
"LB=Requestcount:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPErrorCount",
"LB=Errorcount:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPBytesReceived",
"LB=Bytesreceived:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("HTTPBytesSent",
"LB=Bytessent:
",
"RB=",
"Ord=1",
LAST);
web_reg_save_param("JKMaxThreads",
"LB=Maxthreads:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKMinSpareThreads",
"LB=Minsparethreads:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKMaxSpareThreads",
"LB=Maxsparethreads:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKCurrentSpareThreads",
"LB=Currentthreadcount:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKCurrentThreadBusy",
"LB=Currentthreadbusy:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKMaxProcessingTime",
"LB=Maxprocessingtime:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKRequestCount",
"LB=Requestcount:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKErrorCount",
"LB=Errorcount:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKBytesReceived",
"LB=Bytesreceived:
",
"RB=",
"Ord=2",
LAST);
web_reg_save_param("JKBytesSent",
"LB=Bytessent:
",
"RB=",
"Ord=2",
LAST);
web_reg_find("Text=/manager",
LAST);
web_url("status",
"URL=http:
//{ServerName}/manager/status",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTTP",
LAST);
lr_end_transaction("monitortomcat",LR_AUTO);
//写入TomcatJVM度量数据
lr_user_data_point("TomcatJVMFreememory",atof(lr_eval_string("{JVMFreeMemory}")));
lr_user_data_point("TomcatJVMTotalmemory",atof(lr_eval_string("{JVMTotalMemory}")));
lr_user_data_point("TomcatJVMMaxmemory",atof(lr_eval_string("{JVMMaxMemory}")));
//写入Tomcatwebserver度量数据
lr_user_data_point("TomcatHTTPMaxthreads",atof(lr_eval_string("{HTTPMaxThreads}")));
lr_user_data_point("TomcatHTTPMinsparethreads",atof(lr_eval_string("{HTTPMinSpareThreads}")));
lr_user_data_point("TomcatHTTPMaxsparethreads",atof(lr_eval_string("{HTTPMaxSpareThreads}")));
lr_user_data_point("TomcatHTTPCurrentsparethreads",atof(lr_eval_string("{HTTPCurrentSpareThreads}")));
lr_user_data_point("TomcatHTTPCurrentthreadbusy",atof(lr_eval_string("{HTTPCurrentThreadBusy}")));
lr_user_data_point("TomcatHTTPMaxprocessingtime",atof(lr_eval_string("{HTTPMaxProcessingTime}")));
lr_user_data_point("TomcatHTTPRequestcount",atof(lr_eval_string("{HTTPRequestCount}")));
lr_user_data_point("TomcatHTTPErrorcount",atof(lr_eval_string("{HTTPErrorCount}")));
lr_user_data_point("TomcatHTTPBytesreceived",atof(lr_eval_string("{HTTPBytesReceived}")));
lr_user_data_point("TomcatHTTPBytessent",atof(lr_eval_string("{HTTPBytesSent}")));
//写入Tomcatservletcontainer度量数据
lr_user_data_point("TomcatJKMaxthreads",atof(lr_eval_string("{JKMaxThreads}")));
lr_user_data_point("TomcatJKMinsparethreads",atof(lr_eval_string("{JKMinSpareThreads}")));
lr_user_data_point("TomcatJKMaxsparethreads",atof(lr_eval_string("{JKMaxSpareThreads}")));
lr_user_data_point("TomcatJKCurrentsparethreads",atof(lr_eval_string("{JKCurrentSpareThreads}")));
lr_user_data_point("TomcatJKCurrentthreadbusy",atof(lr_eval_string("{JKCurrentThreadBusy}")));
lr_user_data_point("TomcatJKMaxprocessingtime",atof(lr_eval_string("{JKMaxProcessingTime}")));
lr_user_data_point("TomcatJKRequestcount",atof(lr_eval_string("{JKRequestCount}")));
lr_user_data_point("TomcatJKErrorcount",atof(lr_eval_string("{JKErrorCount}")));
lr_user_data_point("TomcatJKBytesreceived",atof(lr_eval_string("{JKBytesReceived}")));
lr_user_data_point("TomcatJKBytessent",atof(lr_eval_string("{JKBytesSent}")));
return0;
}
(2)、然后在Run-time中设定数据收集的间隔,如图7.5所示:
图7.5设置数据收集间隔
(3)、最后在Controller中设置脚本运行,这样场景运行完毕后,即可在Analysis中添加“UserDefinedDataPoints”查看收集到的Tomcat性能数据,如图7.6所示:
图7.6在Analysis中查看Tomcat性能数据
这种收集数据的弊端是需要通过网络请求Tomcat的页面,会对Tomcat服务器的性能造成一定的影响,如果Tomcat出现性能瓶颈,则收集数据时也可能碰到连接错误,会出现收集不到数据点的情况:
CollectMetrics.c(260):
Error-26630:
HTTPStatus-Code=401(Unauthorized)for"http:
//127.0.0.1:
8080/manager/status"
CollectMetrics.c(260):
Error-26377:
Nomatchfoundfortherequestedparameter"JVMFreeMemory".Checkwhethertherequestedboundariesexistintheresponsedata.Also,ifthedatayouwanttosaveexceeds102480bytes,useweb_set_max_html_param_lentoincreasetheparametersize
因此,最好把收集数据点的间隔设大一点,例如5秒~10秒收集一个数据点。
4、JMX监控Tomcat
JMX(JavaManagementExtensions)是一个为应用程序植入管理功能的框架。
JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。
可以利用JDK的JConsole来访问TomcatJMX接口实施监控,具体步骤如下:
(1)、首先,打开Tomcat5的bin目录中的catalina.bat文件,在头部注释部分的后面加上:
setJAVA_OPTS=%JAVA_OPTS%-Dcom.sun.management.jmxremote.port=8999-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=false
(2)、如果已经配置好,则可使用JConsole打开监控平台查看Tomcat性能,如图7.7所示。
图7.7使用JConsole查看Tomcat性能
由于JMX提供的接口是任何Java程序都可以调用访问的,因此我们可以编写JAVA程序来收集Tomcat性能数据,具体代码如下所示:
importjava.lang.management.MemoryUsage;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjava.util.Formatter;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Set;
importjavax.management.MBeanAttributeInfo;
importjavax.management.MBeanInfo;
importjavax.management.MBeanServerConnection;
importjavax.management.ObjectInstance;
importjavax.management.ObjectName;
importjavax.management.openmbean.CompositeDataSupport;
importjavax.management.remote.JMXConnector;
importjavax.management.remote.JMXConnectorFactory;
importjavax.management.remote.JMXServiceURL;
publicclassMonitorTomcat{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
try{
StringjmxURL="service:
jmx:
rmi:
///jndi/rmi:
//192.168.1.100:
8999/jmxrmi";//tomcatjmxurl
JMXServiceURLserviceURL=newJMXServiceURL(jmxURL);
Mapmap=newHashMap();
String[]credentials=newString[]{"monitorRole","QED"};
map.put("jmx.remote.credentials",credentials);
JMXConnectorconnector=JMXConnectorFactory.connect(serviceURL,map);
MBeanServerConnectionmbsc=connector.getMBeanServerConnection();
ObjectNamethreadObjName=newObjectName("Catalina:
type=ThreadPool,name=http-8080");
MBeanInfombInfo=mbsc.getMBeanInfo(threadObjName);
StringattrName="currentThreadCount";//tomcat的线程数对应的属性值
MBeanAttributeInfo[]mbAttributes=mbInfo.getAttributes();
System.out.println("currentThreadCount:
"+mbsc.getAttribute(threadObjName,attrName));
//heap
for(intj=0;jSystem.out.println("###########"+mbsc.getDomains()[j]);
}
SetMBeanset=mbsc.queryMBeans(null,null);
System.out.println("MBeanset.size():
"+MBeanset.size());
IteratorMBeansetIterator=MBeanset.iterator();
while(MBeansetIterator.hasNext()){
ObjectInstanceobjectInstance=(ObjectInstance)MBeansetIterator.next();
ObjectNameobjectName=objectInstance.getObj