tomcat 性能之谜

原创 2013年03月28日 10:21:13

从接触java web开发,并用tomcat部署了第一个jsp应用已经有好些年了,一直以来javaweb应用的部署都是依赖类似tomcat这种符合servlet规范的容器。应用部署在容器中运行,过往的经验感觉应用的表现在各种容器中其实差不太多,倒也没太在意容器本身的性能。

在最近的一个项目中,严重依赖了tomcat的comet机制,并针对这个项目做了比较全面的性能测试,感觉整体性能表现并没有达到预期。开始猜想tomcat comet机制的实现不是存在一些性能问题,于是开始对tomcat容器本身的性能进行一个摸底测试,做一些定量的分析。

开始之前,我们先进行一个猜测,形成一个预期值,并根据实测结果来检验与预期值的差异。过去很多tomcat应用项目都做过针对应用本身的性能测试,测试结果tps根据应用类型的不同在几百到一千左右,所以一直以来形成一个感觉就是tomcat的tps大概也就几千。由于这次是测试tomcat容器本身,所以我们排除掉应用的执行延迟,只使用一个最简单的应用类型:echo 响应。 tomcat的版本选择了线上常用的 6.0.33(bio模型)和 7.0.35(comet nio 模型)。

测试环境如下:

      
客户端-服务端:
     model name: Intel(R) Core(TM) i5-2320 CPU @ 3.00GHz     
     cache size: 6144 KB     
     cpu cores:  4     
     jdk:        1.6.0_30-b12
     network:    1000Mb

     memory:     -Xms256m -Xmx256m
     Linux:      centos 5.7, kernel 2.6.18-274.el5


测试工具:
     apache benchmark

版本:
     tomcat          6.0.33
     tomcat          7.0.35
      
    

首先,实现了一个EchoServlet,它返回固定1k左右的字符串, 并且关闭了http的keep-alive机制,tomcatconnector 采用默认的bio模型。 测试结果还是挺让人吃惊的,tps均值达到了22000左右(如下所示)

tomcat 6.0.33 bio servlet 测试结果

      
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/


Benchmarking 10.28.170.56 (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Completed 1000000 requests
Finished 1000000 requests




Server Software:        Apache-Coyote/1.1
Server Hostname:        10.28.170.56
Server Port:            8118


Document Path:          /tomcat-test/echo?t=1111111111111111111111******(填充至1k左右)
Document Length:        1024 bytes


Concurrency Level:      32
Time taken for tests:   45.096 seconds
Complete requests:      1000000
Failed requests:        0
Write errors:           0
Total transferred:      1206002412 bytes
HTML transferred:       1024002048 bytes
Requests per second:    22175.13 [#/sec] (mean)
Time per request:       1.443 [ms] (mean)
Time per request:       0.045 [ms] (mean, across all concurrent requests)
Transfer rate:          26116.47 [Kbytes/sec] received


Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       3
Processing:     0    1   0.8      1      30
Waiting:        0    1   0.8      1      29
Total:          0    1   0.8      1      30


Percentage of the requests served within a certain time (ms)
  50%      1
  66%      2
  75%      2
  80%      2
  90%      2
  95%      2
  98%      2
  99%      2
 100%     30 (longest request)


Cpu usage:   180%	

注:测试过程中产生过2次吞吐抖动,rps降至16000左右,随后多次重复测试又恢复正常
      
    

接着,我们换用 tomcat comet 实现EchoServlet,connector采用了nio模型,使用了tomcat7.0.35版本(6.x版本的NIO模型很不稳定,bug较多)测试结果tps略微低于bio模型,但nio模型在测试过程中,多次出现异常导致ab测试直接中断。

tomcat 7.0.35 nio servlet 测试结果

      

This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/


Benchmarking 10.28.170.56 (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Completed 1000000 requests
Finished 1000000 requests




Server Software:        Apache-Coyote/1.1
Server Hostname:        10.28.170.56
Server Port:            8118


Document Path:          /craft-cell-test/echo?t=1111111111111111111111******(填充至1k左右)
Document Length:        1024 bytes


Concurrency Level:      32
Time taken for tests:   49.072 seconds
Complete requests:      1000000
Failed requests:        0
Write errors:           0
Total transferred:      1206000000 bytes
HTML transferred:       1024000000 bytes
Requests per second:    20378.37 [#/sec] (mean)
Time per request:       1.570 [ms] (mean)
Time per request:       0.049 [ms] (mean, across all concurrent requests)
Transfer rate:          24000.31 [Kbytes/sec] received


Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       2
Processing:     0    1   3.0      1     359
Waiting:        0    1   1.3      1      36
Total:          0    2   3.0      1     359


Percentage of the requests served within a certain time (ms)
  50%      1
  66%      2
  75%      2
  80%      2
  90%      2
  95%      2
  98%      3
  99%      3
 100%    359 (longest request)


Cpu usage:   200%


注:测试过程中经常出现连接被意外重置导致 ab 中断(apr_socket_recv: Connection reset by peer (104)),另有一次出现5个请求失败,可以推测 tomcat nio connector 的实现还存在潜在 bug
      
    

从上面的摸底测试中,我们发现tomcatbio模型表现相对稳定,nio模型还存在潜在bug经常使测试中断或出错。并且bio模型其实针对echo型的应用性能表现更佳,nio模型更适合需要保持大量连接的场景。
而且tomcat的性能表现也远远超过我们之前的预期,那么为什么我们的应用部署到tomcat中后,在性能测试中表现不佳,tps经常只有几百不足一千?是我们应用写的太差导致的?
首先让想到的是,我们现在开发java web应用通常采用一些框架,例如ssh或ssi,会不会跟框架有关?
在性能测试echo场景下,用不到spring、hibernate或ibatis之类,于是仅把struts引入,实现一个EchoAction来测测看呢。

tomcat 7.0.35 nio struts2 dynamic method invocation 测试结果

      
      
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/


Benchmarking 10.28.170.56 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests




Server Software:        Apache-Coyote/1.1
Server Hostname:        10.28.170.56
Server Port:            8118


Document Path:          /craft-cell-test/echo?t=1111111111111111111111******(填充至1k左右)
Document Length:        1024 bytes


Concurrency Level:      32
Time taken for tests:   9.264 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      116501165 bytes
HTML transferred:       102401024 bytes
Requests per second:    10793.99 [#/sec] (mean)
Time per request:       2.965 [ms] (mean)
Time per request:       0.093 [ms] (mean, across all concurrent requests)
Transfer rate:          12280.39 [Kbytes/sec] received


Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       2
Processing:     0    3   1.7      3      41
Waiting:        0    3   1.3      2      27
Total:          0    3   1.7      3      41


Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      3
  80%      4
  90%      4
  95%      5
  98%      7
  99%     11
 100%     41 (longest request) 
 

Cpu usage:   280%
      
    

测试结果确实让人挺吃惊的,struts引入后tps下降为原来的一半,并且cpu消耗也上升了不少,而这还只是一个最简单的EchoAction。而现实中的很多web项目,基本都是采用ssh/ssi来开发的,实现业务的action基本也比这个EchoAction复杂不少。这样想来也就可以理解应用性能测试中为什么tps比这种基准性能测试低上一个数量级了。

后记:

最近,负责的一个线上系统调用其他组的webservice接口,总是出现时不时超时的情况,调用接口的响应时间波动范围巨大,从数毫秒到数十秒之间,超时都是超过了30秒的情况。
服务提供方的webservice接口基于cxf实现,和他们的应用一同部署在tomcat中,接口的逻辑很简单,数据传输量也很小(几百字节)那为什么调用响应时间波动如此巨大?
其实这种现象的发生和我们目前的应用开发部署模式有很大关系,一个有一定复杂度的业务应用系统,一般我们现在采用B/S架构,基于ssh框架开发,部署到一个tomcat实例中运行。
这样做的好处是开发简单,部署也简单,但带来的问题是同一个业务应用中,不同的业务场景处理消耗的资源差异巨大,服务没法隔离,服务质量不能得到保障。
比如,一个系统提供了一个查询页面,查询条件由用户指定,查询过程的处理需要访问数据库,那么这个业务的处理耗时就相当不确定,可能很快也可能很慢,由具体查询涉及的数据集大小决定。
同时该系统也提供一个快速k-v式查询服务接口供其他外系统调用,如果此时有很多人在通过查询页面查询一个大数据集,可能很快就消耗完tomcat的线程池,这时外系统再调用k-v快速查询服务接口也不得不等待慢查询的结束才能获取到结果。

目前,我们大多数基于tomcat容器的业务系统都没去做到基于业务来隔离线程池,这也是为什么应用系统在综合业务场景下的性能测试表现不佳,线上一些应用服务接口响应时间的抖动如此巨大,也是与此密切相关。
看来,一开始我们对tomcat容器性能不佳的猜测经实测数据验证是错误的,tomcat本身性能并无问题,有问题的是我们采用的应用开发模式,甚至包括我们选择的一些应用开发框架。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

ORA-01555 caused by SQL statement below

一.发现ORA-01555 alert.log 告警日志: Fri Apr 12 03:11:34 2013 ORA-01555 caused by SQL statement below (Q...

ORA-01555 caused by SQL statement below SQL ID: 9ggx5zvjkgd1t

ALERT日志报错如下: Thu Nov 26 15:34:28 2015 ORA-01555 caused by SQL statement below(SQL ID: 9ggx5zvjkgd1t,...

工作与生活真的可以平衡吗?

最近读到吴军的一篇专栏文章,提到关于公司总是涉及到三方利益:员工、消费者和投资人利益。任何一家公司很难同时兼顾三者利益,都会在这三者中做出选择并力图使之平衡。而作为个体,我们经常也会面临类似这样的处境...

如果两个程序员差不多,选写作能力更好的那个

忘了曾几何时读过一篇文章,是写招聘程序员时,如果两个程序员其他方面都差不多,要从中选择一个,作者的建议就是选写作能力更好的那个,这个说法似曾相识。关于写作这个话题,曾经有不少人都已经写过很好的文章了,...

软件工程师的属性与发展

工作近十年了,[软件工程师] 一直是我职业 title 的中心词,只是前面的修饰语在不断变化,从初级、中级、高级到资深。 其实 [软件工程师] 是一个很泛化的定义,工作现实中软件工程师是被具体分工的...

另一个视角解读计算机编码-补码编码

数学是一个完全抽象的学科,而计算机是这个学科的一种形象化的实现,显然无法处理一些仅在抽象意义上有意义的特殊“数字”,比如无穷之类的东西,。像数学中的加法,乘法这样运算,计算机必须给与实现,然而由于数学...
  • dog250
  • dog250
  • 2011-02-09 21:13
  • 16416

ORA-01555 caused by SQL statement below (Query Duration=38751 sec, SCN: 0x0000.fe5b584a)

今天发现一个报表数据库中SQL运行异常,简单记录一下问题的诊断和解决过程。 问题是在检查ALERT文件时发现的,一个过程运行时间太长而出现了ORA-1555错误。 错误信息: ORA...

ORA-01548: 已找到活动回退段'_SYSSMU1$',终止删除表空间 解决办法

ORA-01548: 已找到活动回退段_SYSSMU1$,终止删除表空间 解决办法http://smfflynj.itpub.net/post/31928/289863验证过程:1 查看所有回滚段信息...

程序员,你为什么值这么多钱?

听说一段时间不加薪,人就会开始思考起和工资有关的问题。消费水平又提升了,能力也进步了,经验也更多了,怎么还没涨工资呢?近两年,有了点余钱就开始考虑起投资来,比如:投资股票首先需要判断的就是关于公司价值...

搞IT的到底怎么了

十年前大概,每一个人都以IT为荣,可是十年后的今天,IT几乎成了一个略带侮辱性的词汇。老婆的QQ截图给我看: 看了以后,思考良久... 高度数眼镜,呆滞,满脸痘痘,卷发(统计意...
  • dog250
  • dog250
  • 2011-09-04 15:19
  • 43463
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)