记一次基于Docker的性能测试

发表于:2019-8-20 11:16

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:冰箱没有油    来源:掘金

  一句话结
   论对于跑在单核CPU上的运算类API, 根据业务需求(最大响应时间)来调试找到最大线程数,然后依据线程数调试出heap大小(主要看年老代的回收次数)
   背景
   断断续续忙碌了几个月,终于自己写的开源项目算是有了雏形,打包成Docker image发布到AWS EC2后,写代码算是告一段落。随之而来的问题就是“我的项目能够支撑多少QPS” ,由于用了Docker, 即变成了“我的项目基于Docker的配置能够支撑多少QPS”, 更进一步细化这个问题的话,有以下几点:
   因为我用了IaaS来创建Linux服务器(选用了Ubuntu)基本配置为 1G RAM 1CPU (2.5GHz)10G+ 硬盘空间(非SSD)?
   当然我并不希望一个Docker container就把上述资源全部占用掉。另一个原因是目前IaaS所提供的内存最小单元是500M,算上系统其他进程的开销,可供一个Docker image 的最大内存资源我定在了400M
   说句题外话,我认为按照服务商提供的最小单元来划分的好处在于:减少开销。500M的费用只有1G的一半,而且将来项目动态伸缩的灵活度高,粒度更小。
   项目是一个OAuth2的Spring boot实现,本身对于IO的要求不高、都是短链接。因为要生成JWT令牌,主要压力在CPU。用了内置的Tomcat,多线程在一个CPU上跑,请求数目一多,99%使用率简直是家常便饭
  第一步:确定性能测试的指标(benchmark)
   俗话说的好, 抛开业务需求来谈IT就是耍流氓。项目是开源项目,业务需求那就只好我自己定了,一般来说我们并不希望用户登录过快(并且并发登录的情况虽然有但是确实比较少见),这次的api (oauth/token) 我定在了2秒的最大值,以此为基础来找出性能瓶颈。
  第二步:确定可调参数
   那么在不改动项目代码的前提下,可以调整哪些参数来提升性能的呢?
   JVM 相关参数,例如 GC、Heap、Thread stackTomcat 相关参数,例如?max-threads、max-connections、accept-count对于计算为主的项目,主要关注点还是在max-threads,设置合理的话可以减少CPU上下文切换带来的性能开销,以及合适的Heap大小来避免频繁触发GC所造成性能抖动。
  第三步:开测 (多图预警)
   虽然标题是基于Docker的性能测试,但是我还是想对比一下用与不用Docker上的性能差异,所以测试会分为两个部分, 以下为jre的基本信息
   ubuntu@ip-xxx-xx-xx-xxx:~$ java -version
  openjdk version "11.0.4" 2019-07-16
  OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
  OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
   ubuntu jre 信息
    ubuntu@ip-xxx-xx-xx-xxx:~$ java -version
  openjdk version "11.0.4" 2019-07-16
  OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
  OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
    docker jre 信息
   3.1 无Docker下的性能测试
   3.1.1 Heap 固定,不同线程数关系图
   50m Heap大小在100个线程的情况下OOM,所以这里为0
  3.1.2 线程数固定,不同Heap大小下关系图
  3.2 基于Docker的性能测试
   直接上对比图
   上图为不限制Docker 容器大小的结果
   上图限制了Docker 容器大小为450M
  3.3 垃圾回收次数(1000QPS)
   上图100 threads 50m Heap 的时候程序直接崩溃了所以为0
  第四步:分析
  4.1 Docker vs 非 docker
   很明显,Docker会带来一定的性能开销,并且随着线程数的增加与QPS的增加,这种开销会更加明显。但是并不是说Docker不好,毕竟性能开销只要多开一个节点就搞定,和Docker带来的便利性相比,几乎可以无视。
  4.2 线程数 与 JVM heap
   这里的讨论仅限于单核CPU负载较高的运算类API,Serial GC
   虽然线程数越多吞吐量越高,但是响应时间会更快的增长
   Heap过小会导致频繁的垃圾回收(年轻代影响较小,年老代最为突出)甚至会OOM导致程序崩溃
   Heap过小时,线程数越大,年老代的回收次数显著增多,年轻代反而会降低(年老代回收为主力)
   Heap过大并不会带来性能提升,但是年轻代回收次数会显著减少,而年老代几乎不受影响
  4.3 一句话结论
   对于跑在单核CPU上的运算类API,?根据业务需求(最大响应时间)来调试找到最大线程数,然后依据线程数调试出heap大小(主要看年老代的回收次数)
  4.4 回到我的开源项目
   很简单,10 threads 100m heap

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号