Tomcat7压测(1)


  • Wednesday, Feb 8, 2017

Tomcat7压测(一)

目的

  • 目的主要有几点:

    • 了解空跑的TomcatQPS能达到多少
    • 测试在Tomcat线程池,等待队列,最大连接数满了的情况下Tomcat的表现
    • 通过压测暴露一些问题及对这些问题的解决
    • 提升性能测试的姿势,算是一种锻炼吧
  • 应该会分几个篇幅来分析,因为压测场景及数据比较多。

  • 本篇主要是最基础的测试,后续会对压测中发现的问题做一些解决

压测

场景

Tomcat配置 maxThreads="300"minSpareThreads="100"connectionTimeout="8000"enableLookups="false"acceptCount="100"acceptorThreadCount="1”
环境 Docker容器内
服务描述 当收到一个请求后,将处理该请求的线程sleep20ms,然后返回response。因为该服务本身几乎不占用任何系统资源,所以在CPU,Mem,IO上是不会产生瓶颈的(实际压测证实),且因为该场景下控制了每个请求的耗时,QPS不高,所以在网络IO上也不会产生瓶颈。因此会影响QPS的只有Tomcat线程池的参数和Tomcat的性能
服务耗时 20ms

数据(整理后)

序号 API TotalTime Requests per second Time per request Tomcat线程池线程数 描述
1 ab -c100 -n500000 -k http://172.16.200.18:8891/Jweb/1 107.443s 4653.62 21.489ms 201
2 ab -c150 -n500000 -k http://172.16.200.18:8891/Jweb/1 72.462s 6900.21 21.738ms 293
3 ab -c200 -n500000 -k http://172.16.200.18:8891/Jweb/1 54.558s 9164.51 21.823ms 273
4 ab -c300 -n500000 -k http://172.16.200.18:8891/Jweb/1 50.134s 9973.28 30.080ms 300
5 ab -c350 -n500000 -k http://172.16.200.18:8891/Jweb/1 44.010 s 11361.12 30.807ms 300
6 ab -c400 -n500000 -k http://172.16.200.18:8891/Jweb/1 41.897s 11934.02 33.518ms 300
7 ab -c500 -n500000 -k http://172.16.200.18:8891/Jweb/1 40.968s 12204.59 40.968ms 300
8 ab -c100 -n500000 http://172.16.200.18:8891/Jweb/1 116.331s 4298.09 23.266ms 102
9 ab -c200 -n500000 http://172.16.200.18:8891/Jweb/1 59.024s 8471.06 23.610ms 201
10 ab -c250 -n500000 http://172.16.200.18:8891/Jweb/1 47.943s 10429.08 23.971ms 251
11 ab -c300 -n500000 http://172.16.200.18:8891/Jweb/1 45.464s 10997.69 27.278ms 300
12 ab -c400 -n500000 http://172.16.200.18:8891/Jweb/1 45.206s 11060.57 36.164ms 300
13 ab -c500 -n500000 http://172.16.200.18:8891/Jweb/1 42.562s 11747.53 42.562ms 300

总结

  • 压测工具使用的是ApacheBench,-c表示并发数,-n表示请求数(即该次压测发起的请求总数),-k表示使用keep-alive。

  • 观察前三组数据,可以发现当并发数小于Tomcat的maxThread时(Tomcat线程池没满时),QPS与并发数成正比(eg.第1、2组数据 6900/4653 ≈ 3/2 = 150/100 )。且每个请求的耗时约为21ms,其中20ms为服务sleep耗时,剩余的1ms为网络通讯和Tomcat处理耗时。客户端Ping服务端耗时约为0.3ms。所以Tomcat处理耗时应该$10^-1$ms级别。

  • 观察第四组数据,由于并发数等于线程池最大对象,当新的请求进来时,需要等待线程释放,导致请求的耗时增加。

  • 为什么前4组数据,Tomcat线程数都大于压测的并发数?

    参考http://hongjiang.info/how-tomcat-implements-keep-alive/

    因为该压测场景下,Tomcat配置的是BIO模式。该模式下对于keep-alive的请求Tomcat线程会阻塞住并等待请求进来直到超时。通过观察多组数据下服务端TCP链接数,总结得出当带有keep-alive选项时,ApacheBench与服务端之间的建立的每个TCP链接只会处理100个请求(包括失败重试)(待验证是什么原因),当处理完100个请求后,ApacheBench会新建一个TCP链接继续压测,但之前的TCP链接并没有马上关闭。因此这些没有用且没有关闭的TCP连接会继续占用Tomcat线程。

  • 观察不带keep-alive选项的数据,即8-13组数据。可以发现表现和1-8组数据差不多,但由于要建立更多的TCP连接,所以QPS会稍低一些。不过由于每个请求结束后会立即释放Tomcat线程,所以当并发数小于maxThread时,Tomcat线程数≈并发数。多出一两个线程是由于可能一个线程执行完后还没有释放,新的请求就进来了,所以会先创建一个新的线程来执行新的请求。


本文地址