压测那些事

网上的压测博客大多趋于理论,实际落地的很少,系统化的也寥寥。
这里已压测流程为思路,整理压测过程当中落地的经验与技巧。

1、压测工具
一、目前使用的压测工具是loadrunner 11.00 破解版, 该版本有若干问题,1)在设置runtime-setting以后 ,压测图看不到一些响应信息,必须从新复制一遍脚本调试导入(调试过程当中不能设置runtime-setting),这个bug貌似也有不少网友遇到,暂时没找到解决方案。2) 编程支持不太好: 工具备的年代感, 只支持类c的语言编写, 或者dll脚本的导入, 调试起来也不太方便, 自己提供的函数库也不够全面。 3) 环境不一致,压测机linux上, 对本机c语言的一些依赖函数居然不支持) 四、学习稍微有必定的成本,而每次调试脚本也相对比较麻烦。
目前在调研新的压测工具 ngrider简介

目前仍是以loadrunner为主介绍。 本机安装暂不介绍, 压力机安装
目前业务接口和rpc接口主要都是基于http协议的接口(下文简称接口)。

2、压测前准备工做。
1~脚本准备
一、脚本编写与调试
调试以前通常经过抓包工具简单了解被测接口的参数、返回、业务功能;
而后使用postman之类的模拟工具进行参数模拟(建议进行该步骤,接口模拟的复用性很强,能够在任什么时候刻很快速直观的反映目前压测接口的情况,方便各类问题的排查)
以后照葫芦画瓢,根据 脚本示例 替换对应url、参数等,注意post仍是get请求。以后按f5调试便可。
若是调试过程当中遇到问题,为了更方便的排查问题, 可使用http代理(Vuser -》 runtime setting -》internet protocol -》proxy) ,或者使用wireshark等抓包工具, 这里使用代理会出现 1、1中提到的bug。
最后别忘了根据业务需求,进行返回值的判断,有的接口可能成功返回,可是返回值不是咱们指望的,也应该算为失败接口。
ps: 若是涉及到脚本的编程,能够参考 实现MD5加密的两种方式 。可能会遇到上边一中提到的坑。
二、脚本的录制
目前压测的接口都是后端api接口,参数抓包得到,调参基于代码灰盒,没使用过录制工具。
三、脚本的参数化
参数化的设置能够参考 LoadRunner参数化详解 ,参数化准备是个很费劲的事情,压测时须要耐心耐心再耐心, loadrunner对参数的支持虽然比较全面,自己在多线程下的参数使用的场景就须要去理解分配,并且多线程下的调试很麻烦,每每在script里面编辑好了,导入到test中就不灵了,可能重新导入又好使了- -。
2~数据准备
一、参数化使用的数据:
普通的id可使用python或者啥都行生成loadrunner支持的格式(一行一行的就行),很简单一行代码for i in range(200005):print 'key_'+ str(i)+' heheda'+str(i)。
涉及动态计算的数据有两种方法:一、实现计算逻辑如加密。 这种方法成本比较高,只有在实时性场景下才须要。
二、直接利用开发代码中写好的计算方法, 通常这种计算会封装成工具类, 直接在工具类中加入主函数,public static void main(String[] args) {//初始化计算类,调用计算函 数获取相应输出}
二、接口使用的数据
1)数据库数据
oracle 以前使用python连接数据库,python须要安装cx_Oracle 模块,cx_Oracle 依赖一个oracle客户端。 这种方法很坑,光这些搞通就得看你人品好很差,时间就不说了。而后在编程一条条生成数据插入。
mysql 最近发现一个很好用的技巧:存储过程 , 批量插入 ,字符串的拼接函数, concat('11','22',null)。 这个方法插入成本是目前最低的, 准备数据很是简单,支持编程,并且还有一个很大的优点是,使用python插入的效率特别低,一秒大概10条左右,以前也作了一些探索优化好比批量插入等,成本都很高, 而存储过程的效率特别高,10万条数据20s就搞定,python须要一晚上。
2)redis 数据
少许数据好比模拟 几百个并发用户,能够直接 shell脚本 插入, 大量数据可使用 管道 导入。
reids批量删除: EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 uc_loginid*
redis-cli -h 172.16.38.4 -p 6379 -a 'C5HK06NX' keys * | xargs -d ' ' | xargs redis-cli -h 172.16.38.4 -p 6379 -a 'C5HK06NX' del

介此目前须要的数据都准备好了,接下来把数据与脚本关联好。
3~run load test
上述那么多都是在第一步,create scripts, 脚本准备好了,运行第二步。
这里惟一控制的变量就是Vuser, 关于vuser的理解:oadrunner与Jmeter等压测工具原理一致:对被测接口反复进行request,统计request发出与接收时间进行数据展现。loadrunner的一个Vuser,jmeter的一个用户就是一个线程,彼此不干扰(除非脚本有竞争锁),每一个线程不停的执行脚本,把数据汇总给主线程; 而对于每一个request,被压服务器会单起线程处理,而这些线程每每是会相互干扰的(竞争某资源),这个资源就是一种瓶颈。
一个线程一秒内的请求次数只和被测接口的响应时间有关, 假如被测接口响应为0.1s,那么这个线程一秒会请求10次,也就是10hits(request), 乘以线程数就是理论qps。压测中当压力小时,qps与线程数呈线性,斜率就是这个10, 压力大时理论qps会大于实际qps,这时候就得去分析了。
通常Vuser我习惯设置80,vuser增速2~5:这样能够稳步观察系统在逐渐加压的状况的反应, 同时80线程是大于目前线上并发,也会让系统达到瓶颈。同时能够避免没必要要的资源消耗。 压测时间通常持续20分钟左右:不少系统性能(好比redis链接池)是在持续并发下暴露出来,可是时间太长了压测一轮耗时就过久了。

3、压测时的监控
目前使用、了解过的监控工具比较多了:
一、zabbix:只有线上和压测环境有, 而且很差用, 粒度太大,只能反映性能的变化,看不出瓶颈在哪。
二、spring-boot actuator。 配置起来相对简单, 对某个系统的总体概况和实时快照有很好的支持。 使用方便web访问便可。 须要开发配置
三、influxdb 。开发刘晶同窗提供, 粒度比较细、能提供接口级别的监控, 对微服务的追踪排查颇有帮助。
四、jvm监控: jconsole等 , 粒度比较细,图形化支持也不错。能实时反映jvm的各类信息, 很好用。
五、top等命令行式 的监控。 布置成本很低,不少是系统自带, 可是通常都不直观。top –H –p<pid>看哪一个线程消耗资源高。 查看linux系统经常使用的命令
六、业务日志(主要看)、redis日志(看得少)。
七、压力机、被测机 硬件查看
其余可参考 阿里经验

监控也是一块比较耗成本的地方, 布置越细粒度的对排查起来的便捷度、准确度越高,可是成本相应的也会增长。 特别是接口级别的监控,须要一些侵入式(修改代码,增长注解等)的工做,可是压测时每每测试工做在同步进行,不能频繁去改代码,改配置,会给压测带来一些困难。
4、压测结果的分析与调优
首先运行loadrunner的analyze功能, 能够展现一些详细的数据,如90%responsetime,标准差等,做用不大,仅出报告时结果更全面。
主要的分析是系统性能的分析,
传统认为瓶颈可能会出如今某某某地方,而后去监控排查,这种地毯式的排查比较盲目,成本高效率低。
传统流程多是这样的:流程关键指标是否知足要求,若是不知足,须要肯定是哪一个地方有问题,通常状况下,服务器端问题可能性比较大,也有多是客户端问题(这种状况很是小)。对于服务器端问题,须要定位的是硬件相关指标,例如CPU,Memory, Disk I/O, Network I/O, 若是是某个硬件指标有问题,须要深刻的进行分析。若是硬件指标都没有问题,须要查看中间件相关指标,例如:线程池、链接池、GC等,若是是这些指标问题,须要深刻的 分析。若是中间件相关指标没问题,须要查看数据库相关指标,例如:慢查SQL,命中率,锁、参数设置。若是以上指标都正常,应用程序的算法、缓冲、缓存、同步或异步可能有问题,须要具体深刻的分析

就目前的经验,通常先观察日志,保证并发下系统接口稳定无异常。 第二直接观察jvm线程, 通常为http-nio线程等,观察线程状态,堆栈跟踪,根据线程状况去推断性能点。
好比线程有block状态, 那么看是什么锁, 去大胆猜测,尝试涉及对照试验, 而后控制变量法,去佐证。 关于配置,多去看看博客,而后反复调优压测。
特别是开发不断尝试的新架构,新技术,总会遇到大大小小的坑,遇山开山吧, 咱们也要不断提高本身,了解被测系统原理。
目前数据库和redis等组件暂未出现过异常,得益于专业的dba沉淀和较成熟的业界组件。

5、其余经验

mock技巧:在一些很难准备数据的场景下,能够经过修改被测代码放行(原则上是代码流程不能变,该查数据库该rpc不能改)。 对于日益复杂的微服务接口, 能够mock依赖服务(同原则,被mock的流程不能改,只mock返回值)。
就目前机器的性能,java单机性能能达到平均2500qps左右 4c8G1024m (4个cpu核心,8G内存。1024堆内存) 。 每天爱有8核的cpu,最最高(关闭各类日志输出),能达到9000的单机, 算是很高的性能了。
个人观点是,压测目的是找出代码、配置、服务间调用不合理有问题的地方, 而不是非要推算出一个什么参数,或者根据什么公式什么原则推算出线上并发, 毫无心义也毫无科学性。