性能测试需要知道的知识
- 两条线
- 服务器虚拟化(物理机---虚拟机---容器(小型虚拟机linux))
- 关键记住 VMware 虚拟化技术(kvm)
- 08-10年 服务器都是物理机
- 10-15年 服务器是刀片机 +VMware虚拟化技术
- 在一个刀片机中,使用VMware虚拟化技术,可以生成N多个虚拟操作系统,-------要是电信运营商
- 15年左右阿里开始做云产品
- 虚拟化技术发展而来,云服务器,其实就是虚拟操作系统+硬件(虚拟硬件)
- 操作系统
- linux
- centos Ubuntu
- 无图形界面的linux
- 服务器组成:
- 操作系统 +硬件 + 应用服务
- 操作系统:重点学linxu、操作系统原理
- 硬件: CPU 、内存、磁盘
- linux
- 服务的拆分
- 单一 -----------集群
- 把大项目---------拆成小项目-------拆成更小的服务-------微服务
- tomcat: java项目部署服务的最典型的中间
- 项目包 war jar 丢到webapps,秋冬tomcat
- server.xml
- catalina.sh
- 集群:把提供相同能力输出的服务,集成在一起,提供更强能力输出的方式
- 负载均衡(不是平均分配):负载均衡策略
- Nginx:把分布式部署的机器,集成到一起,通过相同能力输出的一个典型软件
- 数据库服务
- 关系数据库:Mysql,postgresql
- 数据库也有集群
- 非关系型数据库:redis,MongoDB
- 时序数据库:influxdb,prometheus -----性能监控平台
- 关系数据库:Mysql,postgresql
- 缩小中间件:
- springboot\springcloud 自带了tomcat
- 操作系统缩小,容器 docker容器
- docker容器,其实就是一个严格的linux系统
- 服务之间通信:协议
- 协议:服务双方,共同遵循的某一个明确的规则,来传递信息
- http/https ---API接口
- 微服务中常用的通信协议:dubbo ---RPC
- 协议:服务双方,共同遵循的某一个明确的规则,来传递信息
- 性能测试:是通过接口来测试服务器的性能
- 用工具,调用接口,接口被调用,从而让服务来处理接口请求
- 接口请求频率越高,短时间内需要处理请求数量就越多,从而测出服务器的性能
- 我们调用接口,就需要遵循接口的协议
- 服务器虚拟化(物理机---虚拟机---容器(小型虚拟机linux))
压测准备
压测场景
压测是有目的的压测,也就是说不是随便找些接口发一通压力,而压测全部的接口也是做不到的或者说无意义的,得有压测的优先级,所以梳理压测场景是很重要的。高优场景主要有下面几个:
- 高频业务场景(都要下拉刷新)
- 关键业务场景,使用频率低,一旦出问题就很严重(微信账号登录)
- 性能高消耗场景(淘宝下单)
- 曾经出现过问题的场景
压测有分单接口压测和场景化压测,前者会简单一些,后者一般是多个接口混合操作以组成一个业务场景,两者在方法上是相通的。
梳理场景时QA需要与RD对齐,确认不同接口的RD负责人、需要压测的接口、系统性能现状以及压测目标;在确定每个接口的压测目标时,要考虑到压测对象是单实例单机房还是集群;在细节上也要确认是单接口压测还是场景化压测,每个接口的流量占比以及优先级,需不需要发足够的压力来触发系统的自动扩容或降级等更进一步的运维能力。
压测环境
在梳理完压测场景后,就要确认压测链路是否完整或符合预期。从一个服务到另一个服务,是不是链路上每一个服务都要压到?下游服务如审计安全等是不是已经考虑到?压测过程中产生的脏数据是否会影响线上数据?可能还要细化到具体下游某个服务不参与压测,如何处理呢?以上种种问题,可能需要推动整个链路相关的业务方进行对应业务改造来适配压测流量,改造完后还要自测验证才能正式开始压测,下面讲一些重点问题,部分内容引用自[文末的参考资料][全链路压测的大概思路]。
脏数据问题
- 如果是在独立的一套环境中操作,不存在该问题
- 影子表:如果是在线上操作,一般将数据写入影子表(与原数据表在schema上一致的不同名表)而非原数据表,实现压测数据与线上数据隔离
- 白名单:指定测试id或者测试账号,在入库后通过统一id区分压测数据,统一处理
- 各类存储层的压测改造,包括缓存层、消息队列、离线数据库等隔离问题。常规方法在压测链路中透传压测标记(也叫流量染色,挺形象的),比如json数据中加
is_stress
标记,存储层根据标记区分压测流量,对压测数据添加指定前后缀再入库等特殊处理
不参与压测的服务如何处理
- mock server:通过录制request和response的方式,对业务的代码实现无侵入
- 服务stub:针对压测流量做处理,类似单测stub,代码stub模拟服务返回response,需要修改代码
- 可以独立部署一套线下环境进行压测。在不影响线上环境的前提下,确保机房,网络,存储,上下游服务与线上保持一致,部署一套独立的环境进行测试,机器与线上隔离,机器出问题不会影响线上。这种方式压测只是针对较少的几个系统进行,因为很难把整个链路所有系统都独立再部署一套,所以应用范围有限。
备注:上游、下游如何定义?
下游的输入来自于上游的输出,假设有服务A、B,A调用了B(或者说A依赖B),那B就是A的上游,A就是B的下游,因为A的输入来自于B的输出(A调用了B,获取B的输出)。
更简单地理解,越接近用户的东西,越是下游。
- 更常见的方法是直接使用线上环境压测,在机器负载低的时间段(如深夜)人工发起或定时发起压测。
压测数据
压测数据其实没什么神秘的,网上说什么按照业务模型产出数据,表达上做了过度抽象反而不好理解,其实意思就是按照业务核心场景将所需要的数据构造出来。关键是要如何科学地模拟线上数据分布,阿里双十一大促中有如下的业务流量漏斗模型,需要给不同场景科学地分配流量比例,这个比例是分析出来的而不是拍脑袋的。可以想象,阿里大促的流量不可能全部最后都走到付款流程,必然很多流量会在前面的流程就结束了,也就意味着,你把全部压测数据都构造成【走到付款场景】的话,你的压测结果是不准确的。
为了更好模拟线上真实的用户使用场景和数据,dump线上数据用来压测是很常见的手段,有两种简单思路:
- 直接回放提前录制的线上流量到压测链路
- 将现成流量copy一部分引流到压测链路
数据dump下来是不能直接用的,一来没加压测标记会污染线上数据,二来涉及用户隐私数据。可以将线上数据作为数据源,经过采集、过滤、脱敏等操作后转变为压测数据,注意点有:
- 确保数据已添加压测标记
- 账户数据要提前完成登录认证等准备工作
- 数据要尽可能跟真实数据保持一致,比如,价格,图片等
- 数据是否有不同设备型号等特殊要求
- 尽量保持和线上相同缓存的命中率
- 其他业务特性上的特殊要求…
压测过程
基本思路跟做质量保障是一样的,从细粒度开始慢慢集成到整个大系统,就像单测->接口测试->集成测试
,压测也是先从简单的开始,一步一步走向全资源全链路,可以参考过程:单接口单机->单接口1/4资源->场景化1/4资源->全量资源压测->拨测
。
单接口单机
在单核(或物理资源少)机器上部署单个服务,排除外部链路、网络等因素,得出自身服务的单核性能情况(单位QPS/core),后续根据此单核性能指标结合压测目标值进行扩容。另外由于是压的单接口单机,无其他接口请求影响,上下游在足够资源的情况下也不会造成瓶颈,所以能确保服务的性能真实值。
单接口单机可以在正式开始大规模压测前提前发现问题,方便RD做针对的性能优化并快速检验优化效果。一部分问题会先在单接口单机压测环节中发现,而一些隐藏得更深的问题,需要延后到全链路大流量压测才能暴露。
单接口1/4资源
单接口单机压测环节,服务端已经完成了部分性能优化,接下来可以进入单接口1/4资源压测,这样是为了验证在单接口单机压测中得到的单核性能数据,在扩容1/4资源下性能是否会线性增长,是否存在性能损耗以及定位损耗源。
场景化1/4资源
单接口压测局限很明显,场景化压测由于引入了上下游服务的其他接口的因素,可以发现单接口压测无法发现的问题,更接近线上用户场景。
全量资源全链路
全部资源到位后,预估的线上压力是否能承受,这一步也是内网压测过程的最后一步。
拨测
除了做内网压测,还要进行拨测验证用户从客户端到服务端的整个带宽资源是否满足预期,内网压测已经确认了业务性能是否达标,因此拨测可以只选择了一个场景进行验证即可。(简单来说拨测相当于压测cdn(内容传播网络),检查各地cdn节点资源是否充足)
压测策略
压测过程也要提前规划好,然后加入一定的人工策略调整。阿里大促还会有预热环节,预先跑一部分流量使得该缓存的数据提前缓存起来。正式压测时细分有几种压测策略
- 峰值脉冲:流量是逐渐变大的一个小坡,还是骤升后保持高峰
- 系统摸高:关闭熔断降级限流等fallback功能,提高压力观察系统性能转折点
- fallback策略验证:开启熔断限流等fallback功能,这些功能是否生效,系统是否还能扛得住
- 破坏性测试:主要为了验证预案的有效性,类似于容灾演练时的预案执行演练,验证后手抢救方案
除了关注前面讲到的指标外,还需要关注各机房流量是否均匀(若不均匀要确认负载均衡是否工作)。
压测收尾
发压环节的结束并不代表压测就到此为止。
数据清理
如果使用了影子表,可能收尾工作会简单一些,只需要下掉影子表即可。如果数据直接落到了线上数据库,可能一大堆压测数据要清理,压测时会对数据染色(比如指定测试账号或流量携带压测标记),逐层透传,最后根据标志识别删除。
常见问题
举例一些可能会发现的典型问题:
- 存在多余的http header,导致额外带宽占用
- spin_lock对RT影响大,优化锁的方式
- 调整nginx worker数量可提高性能
- 不恰当的长链接数
- 代码实现上对象没有较好复用
- cache命中率不符预期
- 业务流程上存在冗余
- 缺少一层cache
- 响应码or错误码可能要继续规范
- 下游服务资源不足(其他监控、存储)
- 内部系统对压测的限流,需要变更配置或者协商解除限制
……
压测总结
给出一个完整的压测过程例子:
- 确定本次的压测目标,预估各项指标的达标值
- 根据服务接口的优先级和使用场景,确认出需要压测的接口
- 梳理压测链路上的服务,确认链路完整性
- 针对压测链路设计的服务进行压测改造
- 准备压测数据,确认压测策略
- 开始压测,监控各项指标,多轮压测检验性能优化效果
- 压测环境清理
- 压测总结报告输出
压测最终应该输出一份报告总结,其实也就是把整个压测方案、过程、结论记录下来,写明压测目标、压测接口、压测数据、压测结论,给出发现的问题并提供优化方案。往往在压测报告完成时,性能问题已经基本被解决了,报告的意义在于梳理前面的整个流程,给后续的压测提供经验指导。
参考资料
Why Averages Suck and Percentiles are Great