一、预研任务介绍和预研目标

任务介绍:

Apache Tomcat是目前较为流行的web服务器,以其技术先进、性能稳定著称,其次它还是一个免费开源的项目。

Tomcat性能分析的意义在于能为日常工作中的一些内存泄露和tomcat crash问题提供参考,本文主要通过一些工具的使用和一些参数的讲解,穿插分析tomcat性能。

预研目标:

通过压力测试以及性能检测工具监控,分析tomcat的性能,并做相应的调优操作。

二、操作步骤

(0)假如测试的并发数过大,请预先对tomcat的maxThreads选项进行设置;

(1)部署测试对象

以供电局需求侧分析项目作为web压力测试对象,在其web.xml中将spring security的过滤器模块注释掉,并将其部署上tomcat7.0。

测试是否成功去除spring security拦截,在页面输入http://localhost:8080/DSM/index.jsp,如图1则表示操作成功。

图1 去除拦截后直接越过登录检测登入系统

在dosh下输入JVisualVM [1],开启tomcat性能监控。

至此测试对象已经部署完毕。

(2)使用http_load [2]进行压力测试

http://localhost:8080/DSM/index.jsp
http://localhost:8080/DSM/rest/CommunicatManagement/NoticeboardManagement/NoticeboardViewer?_dc=1376059585323&searchString=&datetimeArray=&page=1&start=0&limit=20
http://localhost:8080/DSM/rest/CommunicatManagement/WorkflowManagement/WorkflowViewer/WorkflowViewer?_dc=1376059701735&searchString=&page=1&start=0&limit=20
http://localhost:8080/DSM/rest/CommunicatManagement/GuestbookManagement/GuestbookViewer?_dc=1376059728941&searchString=&datetimeArray=&page=1&start=0&limit=12
http://localhost:8080/DSM/rest/CommunicatManagement/PowerCutManagement/PowerCutViewerService?_dc=1376059750417&searchString=&datetimeArray=&page=1&start=0&limit=20

在当前目录建立url.txt,内容如上面所示。url.txt内容的意义在于模仿用户进入主界面然后对‘通信管理’模块的所有功能进行并行访问。至于这些url如何获取出来用于测试,你可以用Chrome的Developer Tools或者Firefox的FireBug进行获取。

http_load -p 50 -s 600 url.txt

在dosh下输入如上所示的命令,该命令使用http_load对url.txt中包含的所有url进行并发数为50、为期600秒的压力测试,承受这个压力的即是我们部署的在tomcat上的项目,所以文章虽然叫tomcat分析,但实质也是在对我们的程序进行性能分析。这个时候你可以泡杯茶、散散步静待10分钟的结束,JVisualVM已经在后台默默的工作中了。

(3)数据分析

8559 fetches, 50 max parallel, 2.95904e+07 bytes, in 600 seconds
3457.23 mean bytes/connection
14.265 fetches/sec, 49317.4 bytes/sec
msecs/connect: 0.0851023 mean, 0.341 max, 0.015 min
msecs/first-response: 3458.08 mean, 26924.7 max, 0.225 min
991 bad byte counts
HTTP response codes:
code 200 -- 7568
code 500 -- 991

10分钟到了,在dosh下截获如上所示的压力测试报告。第1行关注其产生了8559个请求,最大并发数为50;第3行关注其每秒处理的请求数为14;第4行关注到每次连接(url里面的内容被处理一次称为一次连接)的平均毫秒为0.0851023(效率高的可怕,这是hibernate的缓存在发挥作用);最后一行我们看到有991条请求当掉了,说明我们的程序性能还是有一定的问题。后台报的错误主要是oracle数据库连接错误,这表明我们的数据库连接池存在一定的问题,需要进一步进行优化。

然而仅凭这些数据,我们还得不出什么直观的性能分析结果,照目前来说,只能算还正常。进一步地,我们需要配合jvisualvm进行分析。

(4)jvisualvm分析

图2 CPU变化图

由图片可以得出,简单的压力测试中CPU的最大占有率达到19%左右,测试环境是在我的个人PC机(I5CPU)上,可见并发对CPU的压力还是很大的。峰值之后的曲线还是比较平缓的,这是CPU的调度能力发挥了作用。假如是对服务器做并发测试的话,这个数据就显得非常重要了。

图3 占用CPU最大的三个方法

Tomcat服务器自带的任务调度和oracle数据库连接占据了最大的CPU,可见我们的主要压力都作用在了oracle和tomcat上了。

图4 堆内存变化图

堆内存中,最大的使用内存才达到414M左右,可见并发对内存的要求不高。曲线非常秘密的那一块说明发生了频繁的产生对象和垃圾回收,JVM的GC还是非常强大的,它一直在背后默默的回收垃圾。除了峰值参考,曲线的另一个意义在于,观察上升和下降的幅度是否大抵一致,如若一直上涨,就有可能是程序出了问题,例如某个for循环写错了,这个时候就会报java.lang.OutOfMemoryError: Java heap space错误。

图5 持久代内存变化图

持久代的内存完全没有波动,说明我们没有发生内存溢出(一般内存溢出都是这里发生的)。为什么一般的内存溢出会发生在这里?PermGen [3]意为permanent generation,即持久代(年老代),程序频繁的读/写数据库将会对这一层造成极大压力,溢出后会报java.lang.OutOfMemoryError: PermGen space错误。

图6 占用内存最大的三个类

这里我们可以得出,字符串类型的操作以及IO读写在压力测试中是发生得最平凡的。

(5)参数调优 [4]和数据库连接池调优

假如你是window 32/64bit,请在tomcat_home/bin下新建setenv.bat并输入以下内容:

set JAVA_OPTS=%JAVA_OPTS%
-Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled

假如你是linux 32/64bit,请在tomcat_home/bin下新建setenv.sh并输入以下内容:

export JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Djava.awt.headless=true"

假如你是以eclipse启动tomcat,请在其vm arguments添加如下内容:

-Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Djava.awt.headless=true

下面对所有参数进行一一解释:

  • -Xms1024m 初始化堆的大小
  • -Xmx2048m 堆的最大值(最大设置为内存值的80%)
  • -XX:PermSize=32m 初始化持久代内存大小
  • -XX:MaxPermSize=512m 最大持久代内存大小
  • -Xss2m 方法栈内存大小
  • -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled 启用并行垃圾收集器
  • -Djava.awt.headless=true 为了不影响linux图形化效果,我们可以添加这个参数

另外,如果你要为你的orcale数据库添加unicode默认支持,则加入如下参数:

-Doracle.jdbc.defaultNChar=true

下一步,我们需要对数据库连接池进行调优:

<!--配置apache dbcp数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:@192.168.0.3:1520:NIKEY" />
<property name="username" value="PHOENIX" />
<property name="password" value="123456" />
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="50" />
<!-- 连接池的最大值 -->
<property name="maxActive" value="100" />
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="10" />
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="5" />
</bean>

备注:所需jar包:commons-dbcp.jar & commons-pool.jar & commons-logging.jar

(6)再测试

使用上面同样的压力测试语句http_load -p 50 -s 600 url.txt,静待10分钟结束。

54995 fetches, 50 max parallel, 1.32363e+08 bytes, in 600 seconds
2406.83 mean bytes/connection
91.6583 fetches/sec, 220606 bytes/sec
msecs/connect: 0.0579369 mean, 0.308 max, 0.013 min
msecs/first-response: 544.293 mean, 6322.84 max, 0.111 min
HTTP response codes:
code 200 -- 54995

54995多个请求全部成功,一秒处理91个请求,每个连接的平均时间为0.05豪秒,效率立即体现出来了。

再看CPU/内存使用图如下:

图6 堆内存变化图

图7 CPU变化图

CPU的变化最大不超过20%,然而调优后需要考虑到由于程序能处理更多的并发,那么也会拉长GC的回收时间,那你所需要注意的是就是这么长的时间里峰值会达到多少,应该在参数配置中予以考虑。

(7)总结

Tomcat的性能足以承受我们日常工作的并发操作,但是需要配置调优参数以防止撑爆,并且为了提高数据库交互的效率我们最好使用连接池技术。

三、参考文献

[1] Java自带的GUI性能监控工具Jconsole以及JisualVM简介

[2] Linux下http_load使用简介

[3] JVM调优总结(十)-调优方法

[4] JVM 几个重要的参数 & Java HotSpot VM Options & Java 6 JVM参数选项大全(中文版)

一、预研任务介绍和预研目标

任务介绍:

Apache Tomcat是目前较为流行的web服务器,以其技术先进、性能稳定著称,其次它还是一个免费开源的项目。

Tomcat性能分析的意义在于能为日常工作中的一些内存泄露和tomcat crash问题提供参考,本文主要通过一些工具的使用和一些参数的讲解,穿插分析tomcat性能。

预研目标:

通过压力测试以及性能检测工具监控,分析tomcat的性能,并做相应的调优操作。

二、操作步骤

(0)假如测试的并发数过大,请预先对tomcat的maxThreads选项进行设置;

(1)部署测试对象

以供电局需求侧分析项目作为web压力测试对象,在其web.xml中将spring security的过滤器模块注释掉,并将其部署上tomcat7.0。

测试是否成功去除spring security拦截,在页面输入http://localhost:8080/DSM/index.jsp,如图1则表示操作成功。

图1 去除拦截后直接越过登录检测登入系统

在dosh下输入JVisualVM [1],开启tomcat性能监控。

至此测试对象已经部署完毕。

(2)使用http_load [2]进行压力测试

http://localhost:8080/DSM/index.jsp
http://localhost:8080/DSM/rest/CommunicatManagement/NoticeboardManagement/NoticeboardViewer?_dc=1376059585323&searchString=&datetimeArray=&page=1&start=0&limit=20
http://localhost:8080/DSM/rest/CommunicatManagement/WorkflowManagement/WorkflowViewer/WorkflowViewer?_dc=1376059701735&searchString=&page=1&start=0&limit=20
http://localhost:8080/DSM/rest/CommunicatManagement/GuestbookManagement/GuestbookViewer?_dc=1376059728941&searchString=&datetimeArray=&page=1&start=0&limit=12
http://localhost:8080/DSM/rest/CommunicatManagement/PowerCutManagement/PowerCutViewerService?_dc=1376059750417&searchString=&datetimeArray=&page=1&start=0&limit=20

在当前目录建立url.txt,内容如上面所示。url.txt内容的意义在于模仿用户进入主界面然后对‘通信管理’模块的所有功能进行并行访问。至于这些url如何获取出来用于测试,你可以用Chrome的Developer Tools或者Firefox的FireBug进行获取。

http_load -p 50 -s 600 url.txt

在dosh下输入如上所示的命令,该命令使用http_load对url.txt中包含的所有url进行并发数为50、为期600秒的压力测试,承受这个压力的即是我们部署的在tomcat上的项目,所以文章虽然叫tomcat分析,但实质也是在对我们的程序进行性能分析。这个时候你可以泡杯茶、散散步静待10分钟的结束,JVisualVM已经在后台默默的工作中了。

(3)数据分析

8559 fetches, 50 max parallel, 2.95904e+07 bytes, in 600 seconds
3457.23 mean bytes/connection
14.265 fetches/sec, 49317.4 bytes/sec
msecs/connect: 0.0851023 mean, 0.341 max, 0.015 min
msecs/first-response: 3458.08 mean, 26924.7 max, 0.225 min
991 bad byte counts
HTTP response codes:
code 200 -- 7568
code 500 -- 991

10分钟到了,在dosh下截获如上所示的压力测试报告。第1行关注其产生了8559个请求,最大并发数为50;第3行关注其每秒处理的请求数为14;第4行关注到每次连接(url里面的内容被处理一次称为一次连接)的平均毫秒为0.0851023(效率高的可怕,这是hibernate的缓存在发挥作用);最后一行我们看到有991条请求当掉了,说明我们的程序性能还是有一定的问题。后台报的错误主要是oracle数据库连接错误,这表明我们的数据库连接池存在一定的问题,需要进一步进行优化。

然而仅凭这些数据,我们还得不出什么直观的性能分析结果,照目前来说,只能算还正常。进一步地,我们需要配合jvisualvm进行分析。

(4)jvisualvm分析

图2 CPU变化图

由图片可以得出,简单的压力测试中CPU的最大占有率达到19%左右,测试环境是在我的个人PC机(I5CPU)上,可见并发对CPU的压力还是很大的。峰值之后的曲线还是比较平缓的,这是CPU的调度能力发挥了作用。假如是对服务器做并发测试的话,这个数据就显得非常重要了。

图3 占用CPU最大的三个方法

Tomcat服务器自带的任务调度和oracle数据库连接占据了最大的CPU,可见我们的主要压力都作用在了oracle和tomcat上了。

图4 堆内存变化图

堆内存中,最大的使用内存才达到414M左右,可见并发对内存的要求不高。曲线非常秘密的那一块说明发生了频繁的产生对象和垃圾回收,JVM的GC还是非常强大的,它一直在背后默默的回收垃圾。除了峰值参考,曲线的另一个意义在于,观察上升和下降的幅度是否大抵一致,如若一直上涨,就有可能是程序出了问题,例如某个for循环写错了,这个时候就会报java.lang.OutOfMemoryError: Java heap space错误。

图5 持久代内存变化图

持久代的内存完全没有波动,说明我们没有发生内存溢出(一般内存溢出都是这里发生的)。为什么一般的内存溢出会发生在这里?PermGen [3]意为permanent generation,即持久代(年老代),程序频繁的读/写数据库将会对这一层造成极大压力,溢出后会报java.lang.OutOfMemoryError: PermGen space错误。

图6 占用内存最大的三个类

这里我们可以得出,字符串类型的操作以及IO读写在压力测试中是发生得最平凡的。

(5)参数调优 [4]和数据库连接池调优

假如你是window 32/64bit,请在tomcat_home/bin下新建setenv.bat并输入以下内容:

set JAVA_OPTS=%JAVA_OPTS%
-Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled

假如你是linux 32/64bit,请在tomcat_home/bin下新建setenv.sh并输入以下内容:

export JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Djava.awt.headless=true"

假如你是以eclipse启动tomcat,请在其vm arguments添加如下内容:

-Xms1024m -Xmx2048m -XX:PermSize=32m
-XX:MaxPermSize=512m -Xss2m -XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Djava.awt.headless=true

下面对所有参数进行一一解释:

  • -Xms1024m 初始化堆的大小
  • -Xmx2048m 堆的最大值(最大设置为内存值的80%)
  • -XX:PermSize=32m 初始化持久代内存大小
  • -XX:MaxPermSize=512m 最大持久代内存大小
  • -Xss2m 方法栈内存大小
  • -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled 启用并行垃圾收集器
  • -Djava.awt.headless=true 为了不影响linux图形化效果,我们可以添加这个参数

另外,如果你要为你的orcale数据库添加unicode默认支持,则加入如下参数:

-Doracle.jdbc.defaultNChar=true

下一步,我们需要对数据库连接池进行调优:

<!--配置apache dbcp数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:@192.168.0.3:1520:NIKEY" />
<property name="username" value="PHOENIX" />
<property name="password" value="123456" />
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="50" />
<!-- 连接池的最大值 -->
<property name="maxActive" value="100" />
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="10" />
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="5" />
</bean>

备注:所需jar包:commons-dbcp.jar & commons-pool.jar & commons-logging.jar

(6)再测试

使用上面同样的压力测试语句http_load -p 50 -s 600 url.txt,静待10分钟结束。

54995 fetches, 50 max parallel, 1.32363e+08 bytes, in 600 seconds
2406.83 mean bytes/connection
91.6583 fetches/sec, 220606 bytes/sec
msecs/connect: 0.0579369 mean, 0.308 max, 0.013 min
msecs/first-response: 544.293 mean, 6322.84 max, 0.111 min
HTTP response codes:
code 200 -- 54995

54995多个请求全部成功,一秒处理91个请求,每个连接的平均时间为0.05豪秒,效率立即体现出来了。

再看CPU/内存使用图如下:

图6 堆内存变化图

图7 CPU变化图

CPU的变化最大不超过20%,然而调优后需要考虑到由于程序能处理更多的并发,那么也会拉长GC的回收时间,那你所需要注意的是就是这么长的时间里峰值会达到多少,应该在参数配置中予以考虑。

(7)总结

Tomcat的性能足以承受我们日常工作的并发操作,但是需要配置调优参数以防止撑爆,并且为了提高数据库交互的效率我们最好使用连接池技术。

三、参考文献

[1] Java自带的GUI性能监控工具Jconsole以及JisualVM简介

[2] Linux下http_load使用简介

[3] JVM调优总结(十)-调优方法

[4] JVM 几个重要的参数 & Java HotSpot VM Options & Java 6 JVM参数选项大全(中文版)

【Tomcat】Tomcat性能分析的更多相关文章

  1. 官方Tomcat镜像Dockerfile分析及镜像使用

    官方Tomcat镜像 地址:https://hub.docker.com/_/tomcat/ 镜像的Full Description中,我们可以得到许多信息,这里简单介绍下: Supported ta ...

  2. Tomcat系统架构分析

    Tomcat系统架构分析 关于这边blog呢,实际开发中并不会用到,但是我觉得还是很有必要认真的写一下.毕竟我们每天在本地撸码的时候使用的就是tomcat来做web服务器.一个常识就是说我们本地在to ...

  3. 7.3.5 Tomcat堆溢出分析(1)

    实战Java虚拟机:JVM故障诊断与性能优化>第7章分析Java堆,本章主要介绍了Java堆的分析方法.首先,介绍了几种常见的Java内存溢出现象及解决思路.其次,探讨了java.lang.St ...

  4. tomcat 源码分析

    Tomcat源码分析——Session管理分析(下)    Tomcat源码分析——Session管理分析(上)     Tomcat源码分析——请求原理分析(下)     Tomcat源码分析——请 ...

  5. Tomcat源码分析——请求原理分析(中)

    前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...

  6. Tomcat源码分析——请求原理分析(上)

    前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程 ...

  7. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

  8. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  9. Tomcat源码分析

    前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...

随机推荐

  1. 454 4Sum II 四数相加 II

    给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0.为了使问题简单化,所有的 A, ...

  2. 移动端UI自动化Appium测试——Windows系统Appium环境配置

    1.安装JDK,官网下载即可,这里用的1.8,环境变量配置 2.安装Android sdk,API >= 17,环境变量配置 3.安装Nodejs,官网http://nodejs.org/dow ...

  3. "言官误国"

    "言官误国" 之前读<明朝那些事儿>的时候,了解到了一个全新的概念,确切的说与之前的印象完全不符合的概念:言官.之前我印象中的言官都是魏征那样的人,为国为民.冒死直谏等 ...

  4. [POJ1509]Glass Beads 后缀自动机 最小循环串

    题目链接:http://poj.org/problem?id=1509 题目意思就是求循环字符串的最小表示. 我们用字符串S+S建立SAM,然后从root开始走n步,每次尽量选最小的. 由于 SAM ...

  5. 1775. [国家集训队2010]小Z的袜子

    [题目描述] 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到 ...

  6. markdown表格中怎么插入逻辑或符号|?

    | 73向下投票接受 | 如果你删除反引号(****),使用|`黑客作品 a | r ------------|----- `a += x;` | r1 a |= y; | r2 并产生以下输出 在这 ...

  7. 飞思卡尔开发板-迅为IMX6开兼容单核 双核 四核Plus开发板

    飞思卡尔开发硬件接口介绍: 核心板参数 尺寸:51mm*61mm CPU:Freescale Cortex-A9 四核 i.MX6Q,主频 1.2 GHz 内存:2GB DDR3 存储:16GB EM ...

  8. 使用JDBC创建出版社和书籍管理系统

    1.需求 已知如下两个表: publisher id name(唯一) address book id isbn name publisher_id 欢迎进入书籍管理系统 1.出版社管理:增.删(na ...

  9. C#在Excel的簡單操作--適用:與DB數據的簡單交互

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  10. java_lock锁

    lock锁是一个接口,jdk5.0新增的接口: 在线程中创建一个他的实现类对象Reentrantlock,默认为fals可以改为true,改为true后是有序的 把操作共享资源的代码放入try中,在t ...