http://blog.sina.com.cn/s/blog_51a7b40e010106b7.html
APACHE的bin目录下。
格式.ab [options] [http://]hostname[:port]/path
参数
-nrequests
//在测试会话中所执行的请求个数。默认时,仅执行一个请求
-c concurrency Number of multiple requests to make
//一次产生的请求个数。默认是一次一个。
-t timelimit
//测试所进行的最大秒数。其内部隐含值是-n50000。它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。
-ppostfile
//包含了需要POST的数据的文件.
-T content-type Content-type header for POSTing
//POST数据所使用的Content-type头信息。
-v verbosity
//设置显示信息的详细程度 - 4或更大值会显示头信息,3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。 -V显示版本号并退出。
-w
//以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
-i
// 执行HEAD请求,而不是GET。
-x attributes
//
-y attributes
//
-z attributes
//
-C attribute
//-C cookie-name=value对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复。
-H attribute
Inserted after all normal header lines. (repeatable)
-A attribute
are a colon separated username and password.
-P attribute
are a colon separated username and password.
//-P proxy-auth-username:password对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即,是否发送了401认证需求代码),此字符串都会被发送。
-X proxy:port
-V
-k
-d
-S
-gfilename
-efilename
-h
//-attributes 设置 属性的字符串.缺陷程序中有各种静态声明的固定长度的缓冲区。另外,对命令行参数、服务器的响应头和其他外部输入的解析也很简单,这可能会有不良后果。它没有完整地实现HTTP/1.x; 仅接受某些’预想’的响应格式。 strstr(3)的频繁使用可能会带来性能问题,即,你可能是在测试ab而不是服务器的性能。
参数很多,一般我们用 -c 和 -n 参数就可以了. 例如:
打开cmd,输入 以下代码。
cd C:\Apache2.2\bin
ab -n 1000 -c 100 http://zf.guqin.com/index/index
----------------------------------------------------------------------------------------------------------------------------------------、
压力测试中JVM内存暴涨原因分析实战 采用apache ab
工作之中写了个小的Web应用,类似于脚手架的demo应用,用spring搭的,在tomcat里运行。
程序写完了,想看看能承受多大的访问压力,遂开始进行压力测试。没有用复杂的loadrunner压测,采用了一个简单的url压测工具http_load,只是单纯地用来压某个url的并发访问。
压测环境介绍:
????? 一台普通的linux服务器,双核,4G内存。
?????tomcat启动内存和最大内存设置为1G,最大处理线程数为默认的200个,http_load模拟200个用户并发访问,持续10分钟
使用lambdaprobe监控tomcat的运行情况,发现jvm内存一直在上涨,从1%增长到90%,最后居然内存溢出了!才压了10分钟而已,感觉到非常奇怪。
于是决定看看jvm的gc日志,在catalina.sh文件中加入jvm参数:
-Xloggc:gclog.vgc -XX:+PrintGCTimeStamps-XX:-PrintGCDetails -XX:+UseConcMarkSweepGC
观察输出的日志文件,发现将近每半秒进行一次GC操作,但是每秒内存还是在均匀上涨1M左右
于是想看看到底是哪些内存对象占用了过多的内存:
???? 首先找出tomcat进程ID,然后运行如下命令,获得其JVM内存对象的占用情况
?1:???????1040160???????33285120??java.util.concurrent.ConcurrentHashMap$Segment?????2:???????1040354???????24968496??java.util.concurrent.locks.ReentrantLock$NonfairSync?????3:????????192962???????23240344??[C?????4:?????????32123???????17892336??[B?????5:???????1040287???????17859608??[Ljava.util.concurrent.ConcurrentHashMap$HashEntry;??
可以看到,java.util.concurrent.ConcurrentHashMap$Segment对象实例最多,且占用了大量的内存。当前JVM内存占用总量为155M,ConcurrentHashMap$Segment,ConcurrentHashMap$HashEntry,java.util.concurrent.locks.ReentrantLock加起来占用了差不多一半的内存!~
回头查看自己的程序代码,看是否有使用ConcurrentHashMap对象,或者滥用该对象的情况。
检查后发现自己程序并没有使用ConcurrentHashMap对象!~很郁闷,到底是哪里在大量的对ConcurrentHashMap进行操作,使得该Map越来越大呢?
经过网上搜索,发现一个比jconsole还强大的jvm监控工具,也是sun推出的,叫做,下载下来该工具后,还可以下载几个插件,丰富其监控功能,甚为好用。
附上一个监控图,非常详细和动态的显示了Eden,S0,S1,Old,Perm区的内存占用情况
由于要分析出到底哪里的ConcurrentHashMap对象被不断的put操作,使其异常庞大,于是首先用visualvm把heapdump出来。在Monitor标签页中有一个Heap Dump按钮,点击就是,该操作会把当前的jvm内存情况导出到一个文件中。
visualvm可以分析dump文件,但是我使用之后感觉非常慢。然后就是另一个工具登场了,HeapAnalyzer ,用该工具来分析dump出的文件。该工具下载下来后为jar文件,直接java -jar运行之。
找出size最大的java.util.concurrent.ConcurrentHashMap$Segment对象:
发现该对象的父对象是org.apache.catalina.session.StandardManager.
查看tomcat源代码发现该类继承自ManagerBase,ManagerBase中果然有一个成员变量为ConcurrentHashMap!
protected?Map<String,?Session>?sessions?=?new?ConcurrentHashMap<String,?Session>();??
该对象存储的就是大名鼎鼎的容器session。
原来,http_load模拟的Url请求没有附带cookie和url重写,也就没有JSESSIONID信息,导致每一个请求,容器都会创建一个新的session。短短10分钟内200个线程并发访问,导致session暴涨。
但是我查看了自己的程序代码,并没有对session进行操作,那么容器是在何时创建新的session呢?
谜底就在于返回的JSP页面。学过jsp/servlet都知道,jsp页面默认有个session变量,查看tomcat目录下的jsp编译后的文件会发现如下代码:
1.response.setContentType("text/html");??
2.pageContext = _jspxFactory.getPageContext(this, request,response,??
3.????????? null, true, 8192, true);??
4._jspx_page_context = pageContext;??
5.application = pageContext.getServletContext();??
6.config = pageContext.getServletConfig();??
7.session = pageContext.getSession();??
8.out = pageContext.getOut();??
9._jspx_out = out;?
getSession()方法会返回当前请求的JSESSIONID对应的session,如果没有就新创建一个session返回。
为了验证该问题,我在返回的JSP页面里加入了
<%@page?session="false"%>??
?不使用session,再次进行压力测试,结果印证了我的想法。
下面是没加session="false"和加上了的两种情况的内存增长图,作为对比,结果非常明显:
这次事件也告诉我不能随便选择测试工具,因为真实用户访问都是会附带cookie信息的,不会出现每个请求都需要创建session的情况。
附:
tomcat使用ConcurrentHashMap来存储session,在并发访问的情况下有更好的性能。有关更多session知识,可以参考:
???? http://java.chinaitlab.com/base/802833.html
???? http://xuehu2009.javaeye.com/blog/524303
例子
D:\apache2\Apache2\bin>ab -n 100 -c 30 http://blog.donews.com/zzw45/
This is ApacheBench, Version 2.0.41-dev <$Revision:1.121.2.12 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking blog.donews.com (be patient).....done
ServerSoftware:
ServerHostname:
ServerPort:
DocumentPath:
DocumentLength:
ConcurrencyLevel:
Time taken for tests:
Completerequests:
Failedrequests:
Writeerrors:
Totaltransferred:
HTMLtransferred:
Requests persecond:
Time perrequest:
Time perrequest:
Transferrate:
Connection Times (ms)
Connect:
Processing: 2625 18634 18972.611703
Waiting:
Total:
Percentage of the requests served within a certain time(ms)
50% 11734
66% 14609
75% 19890
80% 24718
90% 50718
95% 62515
98% 81343
99% 87046
100% 87046 (longest request)