性能压测与调优总结

 2018-04-22 21:53:23     压测  调优  Tsung   148


导读: 为了知道我们的单个服务和整体服务的性能,以便掌握大体情况,以及为以后调整部署方案做评估依据,我们对所有的服务进行了逐级的压测。原以为是个简单的事情,做的过程中才发现要解决好多问题,真不是一项简单的工作。由于之前对压测并不是很了解,很多问题都是遇到后临时Google学习,所以,有一些问题并没有深入理解。

到目前为止,这里的总结是对压测过程和思路的梳理,很多地方并不专业和详细,记录下来,是为以后再做这类事情时,一可以用它来给自己做参考,二来可以继续完善和总结经验。

1、服务说明


这里,先对整体服务架构做一个简单的描述,便于直观理解和内容描述。

deploy

真实的架构比这个要稍微复杂些,涉及到消息队列和数据同步,但那些不在本次的压测的范围内。

由于只压测内网,所以负载均衡暂不考虑。剩下四层分别为:Nginx层、Tomcat层、RPC层、数据层(Redis或MySQL)。

2、压测目标


做这类工作前,首先,一定要先明确目标,是为了什么才压测的,否则容易出现顾此失彼,即浪费时间,又很难有收获。

例如,我们这次的压测目标:

  • 1、掌握各层服务,在模拟简单接口(接口没有任何业务逻辑,直接返回一个字符串)时,单台服务器(或单实例)的QPS情况;

  • 2、掌握各层服务,在请求真实的业务接口时,单台服务器(或单实例)的QPS/TPS情况;

  • 3、如果主要业务接口(或者综合的组合接口)的整体QPS要达到100K,哪些地方会出现瓶颈,怎么调整或部署;

其实前两个目标都是为第三个服务的。

在做第一个目标的过程中,可以适当调整服务器参数、各层服务参数,使所有的环境达到相对较好的条件。同时,逐层压测,得出各层服务的折损情况,以及上下游服务器的扩展关系(一台上游服务器对几台下游服务器或者几台上游服务器对一台下游服务器)。

3、准备工作


所有准备工作都是为目标服务的,也是为快速定位问题服务的。

3.1、压测计划


针对每个目标,都指定一个压测计划,每个计划分步执行。例如,针对第一个目标,可以这样做计划:

步骤编号 测试项目 测试目标
101 单压Nginx 增加压力,QPS成线性增长,单台Nginx QPS能达到400K以上
102 单压Tomcat(简单接口) 掌握Tomcat的QPS和服务器负载情况
103 Nginx + Tomcat(简单接口) 增加压力和Tomcat,QPS成线性增长,QPS能达到100K以上
... ... ...

3.2、压测工具


压测工具有很多,对新手来说,选择时,一定要注意以下几点:

  • 1、压测结果准确,能模拟真实场景

  • 2、报告详细

  • 3、简单易用

结果准确不好定义,最简单的就是和 Apache ab 做一下对比,同时看一下有经验者的使用对比。

这里我使用了免费的 abTsung

Apache ab 是最常用的压测工具,针对单一URL的压测,它是最好的选择。

Tsung 是分布式集群压测工具,能够模拟成千上万的虚拟用户数并发,可以模拟业务场景进行压测。想了解的可以看高并发压力测试工具Tsung

ab 也可以做集群压测,但是需要编写代码,所有,我选择了组合使用。简单压测,或调试压测时,用 ab,正式压测时,用 Tsung

3.3、压测记录


针对压测计划,要制定一份压测记录。如果服务器有监控记录,压测工具有详细的压测报告,压测记录的格式就可以简化许多,否则,压测记录越详细越好。

压测记录是发现问题、定位问题、评估分析的依据,一定要及时的、详细的、真实的记录。

例如,可以按照下面的格式来记录(数据非真实记录):

压测编号 日期 服务部署说明 压力说明 QPS 平均耗时(毫秒) 监控报告 压测报告 参数调整 说明
101001 2018-04-03 1台Nginx 线程:200
请求数:10000
140K 4.6 20180403-1023 20180403-1023 - -
101002 2018-04-03 1台Nginx 线程:400
请求数:10000
280K 4.9 20180403-1030 20180403-1030 - -
101003 2018-04-03 2台Nginx 线程:600
请求数:10000
420K 5.8 20180403-1034 20180403-1034 修改XXX参数,见XXXX文件 参数调整无效
102001 2018-04-03 1台Tomcat 线程:200
请求数:10000
20K 9.2 20180403-1110 20180403-1110 - -
103001 2018-04-04 1台Nginx + 1台Tomcat 线程:200
请求数:10000
20K 9.2 20180404-1323 20180404-1323 修改XXX参数,见XXXX文件 参数调整有效
103XXX 2018-04-05 1台Nginx + N台Tomcat 线程:600
请求数:10000
60K 13.7 20180404-1423 20180404-1423 修改XXX参数,见XXXX文件 可以线性扩展

说明:

1、监控报告:主要是服务器的指标监控,这里的 20180403-1023 是文件夹名称,里面记录的是这次压测导出的监控报告,如果不能导出记录,最好将各指标详细记录下来
2、压测报告:同监控报告一样,记录的是压测结果,Tsung 有导出监控报告功能
3、参数调整:对服务器或服务进行了参数调整,都需要记录,最好以文件方式备份记录
4、说明:一些重要点或重要发现等内容,都可以记录到这里,例如:CPU达到了80%,带宽接近了峰值,QPS已经不能提升等

3.4、压测环境


这里的环境包括一切软硬件环境,最好用表格记录下来。

服务器环境包括:系统版本、CPU核数、内存、网卡吞吐量、内网带宽、硬盘IOPS等,同时,需要注意系统的文件句柄数、TCP协议端口范围(它决定了同时允许多少个用户连接),详细参数调整情况Linux下Http高并发参数优化之TCP参数,测试前,没有必要调整太多参数,只调整这两个即可,可以在测试过程中再调整其它参数,如果有明显变化就使用,否则,维持系统默认配置。

各层服务的服务器环境尽量保持一致,如果出现不一致的情况,对结果影响会很大,加大定位难度。

Nginx环境包括:版本、配置参数、是否开启了debug模式(如果开启,需要关掉)。这里的参数配置,主要有keepalive、worker_processes、worker_cpu_affinity、worker_connections。

user  nginx;
worker_processes  auto;
worker_cpu_affinity auto;

#worker_rlimit_nofile 65535;

events {
    use epoll;
    worker_connections  65535;
    multi_accept on;
}


keepalive_timeout  70;

...

upstream data_api {
    server 192.168.1.2:8083;
    keepalive 300;
}

其它一些参数,也需要根据业务情况进行调整。

Tomcat环境:版本、线程数、连接数等配置。

参数调整遵循一个原则:对于不是很确定的参数(不知其用途或不确定是否能提升性能),尽量保持默认,在压测过程中再考虑调整。

3.5、监控


这个很重要,没有监控指标,压测就没有意义。不光包括被压测的服务器,压力服务器也需要监控。

常有的监控指标有:CPU使用率、CPU负载、内存使用率、内外网卡进出量、硬盘IOPS、HTTP连接数、转发包数、TOP命令下的si开销等。

4、压测


压测是一个反复、枯燥、繁琐的过程。在这种情况下,很容易出问题或遗漏问题,所以,一定要制定好压测计划,并按照计划一步一步的执行,这样就可以避免很多问题,提高效率。

一般来说,Tomcat层和RPC层,扩展服务器(或实例),QPS都应该能成近似线性增长,如果不是,肯定是在某个地方出现了瓶颈。例如,单台Nginx + 单台Tomcat的QPS为20K,那么,2台Tomcat的QPS应该为40K左右,3台Tomcat的QPS应该为60K左右,如果不是,很有可能是Nginx成出现了瓶颈,或者是压力工具的压力不够,需要根据压测结果和监控进行结合分析定位。

为了减少应用程序可能造成的影响,在压测前,可以先用 ab 简单压几下,这样做有两个目的:

  • 1、知道接口在健康情况下的平均耗时,确定程序是否有优化空间,如果有,先暂停压测,做程序优化。

  • 2、找到单服务器的最优压力线程数和请求数。

如果接口平均耗时大于300ms,那么一般来讲是有优化空间的(需要看业务场景,有的接口可能确实比较耗时),优化或者简化程序逻辑后,耗时降到20ms,说明这步操作是值得的。

如果接口平均耗时小于20ms,就没有必要先做优化了,因为这个优化空间太小,而且比较难以定位,这时不如先做压测,以完成压测目标。

做过压测的应该知道,压力太小或太高时,QPS值都会降低,所以,每个服务都有一个合理的压力线程数和请求数,合理的值会使QPS达到最高,小于或大于这两个值(或者范围)时,QPS都会下降。

掌握了单服务器的合理压力线程数和请求数,在横向扩展服务时,就可以快速的确定压力机数或压力机上的压力线程数和请求数,避免盲目的调整压力参数。

一切准备完成后,剩下的就一步一步的压测和记录压测结果,然后分析对比,调整参数,继续压测和记录。

5、定位


定位是最难的,一旦找到,问题迎刃而解。

定位的依据是压测结果记录和监控记录。

一般按照以下几个步骤去定位排查:

1、确保压力合理,如果上来就用很大或很小的压力,很有可能导致横向扩展一两台服务器不能得到改观,从而导致转移视线,定位方向偏离;

2、Nginx层、Tomcat层、RPC层、数据库层,哪层监控出现瓶颈(CPU,内存、网卡等接近最大值或最大值的80%),就横向扩展该层服务,同等压力条件下,瓶颈消失或QPS线性增长,这个瓶颈就不是大问题;

3、如果横向扩展后,问题依然存在,就按照下面的每一项进行检查。

服务报错


检查各层服务日志是否有报错,如果有,先解决掉错误问题。

cpu


在压力足够的情况下,如果CPU利用率上不去,QPS也没有明显变化,查看CPU0负载是否过高,如果负载过高,可能是系统的某些进程在频繁切换CPU。

如果CPU利用率较高,看si是否过高,如果过高,说明可能出现了软中断情况。

以上两种情况需要根据进程任务具体分析。一般通过将进程绑定到CPU核上就可以解决。例如:Nginx、Redis多实例等都会出现这种情况。

如果CPU一切正常,说明问题可能出现在内存或IO,IO包括硬盘IO,网络IO等。

网卡或带宽


任何请求和响应,都是有字节数,任何接口返回的内容在小,在集群高并发的压测情况时,都有可能把网卡或网络堵死。所以,一定要知道内网的传输速度和服务器网卡吞吐量。如果压测期间,内网之间有大文件传输,或者网卡进出量之和接近了网卡的最大吞吐量,都会出现各层服务的CPU利用率不高,QPS也无法提升的现象。

通过查看网卡监控是最好的解决办法。

由于对网络这块不是很熟悉,遇到好多坑,在踩坑的过程中,知道了这里面不只有网卡大小的因素,还涉及到网卡队列、网卡软中断、网卡转发对大小包的差异等因素,这些没有解决好,同样千兆网卡,可能一个32核64G服务器的QPS还不如一个2核8G服务器。

无论是做服务架构设计,还是压测,我觉得都需要对服务器的网络部署有一个大概的了解。如果有给力的运维或网络技术支持,那就最好不过了,能少走好多弯路。如果没有,建议选择成熟的云服务器(选择时,最好做一下测试对比),它们的产品已经根据业务场景对服务器做了优化,几乎不用关心服务器的软硬件问题,减少很多麻烦。

内存


这个没什么好说的,看内存监控使用情况,一般内存使用超出了,服务会有报错信息。

IO


查看磁盘IO是否使用较高,如果涉及到读写文件的操作,都有可能出现问题。

数据库


很多时候,瓶颈都是在数据库。而解决数据库的瓶颈问题,又是一项复杂的问题。

由于数据库是独立部署的,所以,如果是数据库出现瓶颈,通过对数据库服务器的监控,就可以发现问题。

在并发量小的情况下,一般优先考虑数据库使用方式是否正确,SQL是否高效;而在高并发情况下,一般要使用分库或集群部署等方式来解决。

最后


如果确定问题是在CPU或IO,但又无法确定具体是什么导致的,可以使用 Profiler 来解决。详细内容请看使用火焰图做性能分析

6、总结


整个测试完成后,无论是否完成目标,都要做个总结,没有别的原因,因为它能带来很多好处。

按照这个流程,我们发现了之前在内网压测无法提升QPS的问题,并找到每层服务的瓶颈值,为横向扩展各层服务提供了依据。


参考: