Java编写的Web应用在不同部署方式下的差异

项目开发结束,马上就要部署上线了。而Java Web应用的部署方式有很多,为了合理的利用资源,我们想先对每种方式进行测试,然后选择最优的作为我们的方案。因此我让组里的实习生YWD同学做了一些测试工作。

我们的项目特点是:

1、是Web类的项目,用SpringBoot开发

2、有一些job类的定时任务

3、项目数量多,单个项目规模小

这里将YWD同学的测试结果记录下,便于今后参考(话说YWD同学做事还是挺细致的)。

关于项目的不同部署方式对服务器的资源占用影响

应用在服务器上的部署方式对应用的资源占用影响巨大,特别是对于 像java这样的应用,而我们目前对各种应用不同的部署方式的占用资源情况了解还 不是很明确,所以对一个这方面的测试显得尤为重要。
用来测试的项目就是之前的日报管理系统,其中外挂了三个定时任务,分别是:

  • 每秒钟向数据库做10次查询,模拟数据库的操作。
  • 每秒钟求出30万内所有质数的和,模拟密集型运算。
  • 每秒钟向文件中写入一个长度为10000的字符串,模拟io操作。

然后新加了一个用于测试并发的接口,由于是用于测试,所以我直接让其返回“helloWorld”即可。
测试的种类如下

  1. 单项目测试
    1. 测试单项目,打包成jar包直接运行的资源占用
    2. 测试单项目,打包成war包交于spring管理运行的资源占用
    3. 测试单项目,将定时任务与项目分离,分别打包成jar包运行的资源占用率
    4. 测试单项目,将定时任务与项目分离,分别打成war包放在tomcat下运行的资源占用率
  2. 多项目测试
    1. 将多个项目打包成war包,放在tomcat下运行,每个项目使用独立的端口的资源占用率
    2. 将多个项目打包成jar包,直接通过java-jar运行的资源占用率
    3. 将多个项目打成war包,放在tomcat下运行,每个项目都使用相同的端口的资源占用率

下面是测试的结果

单个项目的测试

首先将项目打包成jar包,然后进行测试。 测试的结果:

  1. cpu占用:1.3-2.0左右浮动
  2. mem占用:稳定4.9%
  3. 并发:使用ab命令测试结果
    1. ab -c 100 -n 100000 url 完成时间为9.558seconds
      吞吐量为10462req/s
      在高并发的情况下,cpu的占用率大概稳定在370%左右,mem的占用率没有发生变化

然后将项目放置在tomat中运行启动 测试的结果:

  1. cpu占用: tomcat中的cpu占用不是很稳定,总体在1.0%-3.0%间波动
  2. mem占用: 稳定占用在5.7%
  3. 并发:使用ab命令测试结果
    1. ab -c 100 -n 100000 url 完成时间为9.345seconds
      吞吐量可以达到10701req/s
      在高并发的情况下,cpu占用率大概也稳定在370%左右,但是mem占用率发生上升,最后在10%左右稳定。

再将项目web部分与定时任务部分分开,全部打包成jar的形式运行 测试结果:

  1. 空闲时刻的资源占用率:
    1. web部分运行较为稳定,cpu占用在0%(因为处于空闲状态)mem占用率在3%左右
    2. 定时任务的运行也比较稳定,cpu在执行任务时会上升至0.7%左右徘徊,空闲时维持在在0.3%左右,内存占用率基本没有变化,维持在2%左右
  2. 高并发情况下的资源占用率:
    1. web端进程在高并发情况下,用ab -c 100 -n 100000 url测试接口,完成时间为9.05seconds
      吞吐量可以达到11042req/s
      ,进入高并发时,cpu上升至250%左右,内存上升至5%左右。
    2. 定时任务进程依旧没什么变化,依然为休眠时0.3%左右的cpu占用率,执行时0.7%的占用率,mem占用率稳定2%

最后测试将项目分开,web端放置在tomcat中运行,然后定时任务独立打包成jar用java直接执行的情况。 测试结果:

  1. 空闲时刻的资源占用率:
    1. web部分运行较为稳定,cpu占用在0.3%左右,mem占用在5.5%左右
    2. 定时任务的运行比较稳定,cpu在执行任务时会上升至0.7%左右徘徊,空闲时维持在在0.3%左右,内存占用率基本没有变化,维持在2%左右
  2. 高并发情况下资源占用率:
    1. web部分在高并发情况下,用ab -c 100 -n 100000 url测试接口,完成时间为9.35seconds
      吞吐量大概为10678req/s
      ,进入高并发时,cpu上升至300%的占用,内存上升至10%左右稳定。
    2. 定时任务的运行比较稳定,没有受到影响。
类型 空闲时CPU(%) 空闲时MEM(%) 高并发时CPU(%) 高并发时MEM(%) 并发量(req/s) 备注
将项目整体打成jar包直接运行 1.3-2.0 4.9 370 无变化 11042 -
将项目整体打成war包放入tomcat运行 1.0-3.0 5.7 370 10% 10678 -
将项目web应用与定时任务分离,然后均打成jar包处理 web: 0.0 定时任务:0.3-0.7 web: 3.0 定时任务:2.0 web:250 定时任务:无变化 web:5 定时任务:无变化 11042 -
将项目web应用与定时任务分离,web应用用tomcat运行,定时任务直接用jar运行 web: 0.3 定时任务 0.3-0.7 web:5.5 定时任务:2.0 web:300% 定时任务: 无变化 web:10 定时任务: 无变化 10678 -

经过上述测试,可以得出结论,对于单个项目而言,部署方式基本上不会影响并发量的大小,而对cpu的影响也比较小,我们发现,在高并发情况下时,无论是cpu的占用情况,还是内存的占用,都是 将项目分离然后单独打成jar包的形式,资源占用最小;
同时也发现,将项目的定时任务模块分离,可以大大减少项目在高并发情况下,对cpu的占用。

多个项目的测试

接下来进行的,是多个项目在服务器上不同的部署方式。 我的计划是将这个日报项目复制三份,手动模拟三个项目。 端口测试时,所有端口都处于ab测试状态。

首先是多个项目均打包成war包的形式,在tomcat下以不同的端口运行,这个也是我们目前服务器上实施的方案。 测试结果:

  1. 空闲时刻的资源占用率:
    1. cpu占用:当三个项目同时奔跑时,cpu的占用在1.5至3.5之间跌宕起伏
    2. 内存占用:内存占用非常稳定的表现在10.7的水平。
  2. 高并发时刻的资源占用以及并发量:
    1. 在高并发状态下时,对所有接口都使用 ab-c 100 -n 100000 url命令测试,发现所有接口的完成时间都上升到原来的两倍,吞吐量也降低为原来的一半,同时cpu占用率达到530%,

内存的占用居然没有发生变化,甚至还下降了一些,真是匪夷所思。

然后再对所有项目都打包成jar包直接运行的方式来进行新一波的测试,看看结果如何。 测试结果:

  1. 空闲时刻的资源占用率:
    1. cpu占用:空闲状态时,每个cpu的占用都是比较正常的,与单独一个项目在运行时没有什么区别,大概占去0.3%-0.7%
    2. 内存占用:空闲状态的内存占用也是非常的正常,大概占去3.6%。
  2. 高并发状态下的资源占用情况:
    1. 在高并发状态下时,每个项目起初的cpu占用率都在200至300间极具波动,但最后都稳定在180%左右,每个项目的内存都攀升到7%-8%,

且所有的接口的吞吐量都降低为原来的一半,也就是5000reqs/s左右,看来分开部署和一起放入tomcat中完全没有可比性,在内存上被碾压了。
最后是对另一种比较特殊的情况,即项目均部署在tomcat中,但是均部署在同一个端口下面,让我们来看看这种 方式它有什么特点。 测试结果:

  1. 空闲时刻的资源占用率:
    1. 空闲时刻cpu占用率达到了2.3%-4.7%之间来回波动,偶尔还会冲到十几的占用率,要知道这可只是空闲的占用啊。
    2. 空闲时刻内存的占用比较稳定,保持在11%的样子没有发生什么改变。
  2. 进行高并发测试时各类资源的占用以及吞吐量
    1. 高并发状态下时,整体的cpu占用率在460%到500%之间波动,比分端口部署稍微低一些,内存同样又稍微下降了一些,在8.7%左右徘徊,真是匪夷所思,吞吐量整体在6000reqs/s以上,有个任务可以达到7000reqs,

看起来比分端口部署在吞吐量上稍微好一些。
测试表格

类型 空闲时CPU(%) 空闲时MEM(%) 高并发时CPU(%) 高并发时MEM(%) 并发量(req/s) 备注
在tomcat的不同端口下同时运行三个项目,表现为一个进程 1.5-3.5 10.7 530 下降至 8.7 3*5000+ -
在tomcat的相同端口下运行三个项目,以路径名区分,表现为一个进程 2.3-4.7 偶尔达到10+ 11.1 460-500 下降至8.7 3*6000+ -
每个项目都打包成jar的方式,独立运行,表现为三个进程 3*0.3-0.7 3*3.6 3*180 3*7.0-8.0 3*5000+ -

总结

对于多项目部署,经过测试,发现统一端口部署在高并发时,cpu占用以及吞吐量上都是要略微优于分端口部署的,而单独项目打包部署在内存上存在占用较大的情况,在别的方面也没有优势。
所以我认为项目如果没有过于明显的区分端口需要,可以放在同一个端口下,以路径的方式去区分,可以起到稍微提升cpu占用以及吞吐量的好处。

备注:我们最终还是考虑采用不同应用分端口部署,原因是避免一个应用出问题挂掉后,对其他应用造成关联影响。

这个来自PHP-FPM的教训,我们之前PHP应用就是一台服务器上的项目全部公用一个PHP-FPM,结果一个应用导致PHP-FPM堵住,其他所有应用都被堵住了。

关于tomcat部署的一些细节

  1. tomcat可以做到直接运行war包而不用解压,在server.mxl中可以做配置。在启动时间上会稍微久一些,但是启动后的资源占用以及接口测试性能都与正常的解压运行没有区别。
  2. 在测试时,出现了一个非常棘手的问题,即在覆盖war包时,tomcat无法对新覆盖的war包自动解压更新项目,必须通过重启tomcat或者删除老的war包再复制新的达到更新的目的,

后来在与测试服务器对比时,更改了复制命令 cp更改为cp -i,居然又可以自动识别war包被覆盖了,我尝试将cp命令改回去,结果发现它并不会还原,换句话说,在我修改过cp 命令后,这个war包的覆盖自动重启功能正常了,真是匪夷所思。

这个还要继续排查下,我试了下确实不会重新reload,但是和cp加不加-i参数没关系。

此外,测试出多个项目部署在同一个端口下时,对一个项目的重新部署不会影响其他项目的运行