压测-线上全链路压测实践总结篇

总结:为什么要做线上全链路压测?典型应用场景以及5种典型的线上压测方案,全链路压测的方法论,典型性能问题总结

什么是全链路压测

全链路压测是可以在现网环境实施的尽可能模拟真实环境流量的场景化压测,通过全链路压测,业务可以探测系统级复杂链路的性能瓶颈,辅助其作出相应的容量规划。

随着分布式架构和业务快速发展给业务系统带来了不确定性,分布式环境的任何节点都可能成为瓶颈/短板/问题。拿如下这个简单系统为例,用户对系统的一次请求,经过负载均衡、接入层服务、逻辑服务,最终请求到了外部服务,同时产生的用户数据也被存储下来。

在这条链路中,其中任何一个服务节点或者存储节点出现性能瓶颈,都可能导致整个系统受到影响。

当然,在得出这条结论之前需要具备一些前提条件:第一、拥有“上帝视角”获取到了调用接口背后的链路拓扑图;第二、同时拥有完备的监控数据做支撑。而这些可能是我们日常进行普通压测所缺乏的。普通压测更多的关注在发压能力以及发压端,对于被压端却是黑盒的。普通压测与全链路压测的区别总结如下:

可见全链路压测的特点在于:

  1. 支持脏数据隔离与流量隔离;
  2. 支持高负载等异常发现能力,实现压测任务自动化熔断;
  3. 支持压测接口背后依赖的的节点链路透视;
  4. 支持实时监控被压链路的指标数据;

为什么要做线上全链路压测?

举一个典型例子:某大促期间,系统在0点,出现大面积瘫痪,重启后又瘫痪;

为什么出现这个问题?是系统间存在依赖关联,对整个全交易链条上的各个环节的系统承压能力不清楚。

最好的办法就是模拟完全的真实情况来做到提前实战演练。即线上全链路压测:

  • 提早发现问题,保障重大活动时系统稳定运行;
  • 找出各个系统的性能瓶颈,明确优化目标;
  • 精准的容量评估:压测结论作为申请扩容资源的依据,活动结束后再归还资源,这样做到成本最低化。

典型的线上全链路压测应用场景

五种典型线上压测方案

简述几种典型的线上压测方案,并重点分析每种方案可能的风险和踩坑。

阿里全链路压测方案

通过模拟线上真实流量,对整条链路进行全方位、安全、真实的压测

核心实现思路是:通过压测流量全局识别、透传,数据进影子区域,且监控区分压测流程和业务流量。

  • 流量标记:业务系统、中间件改造,全链路标记压测流量
  • 分区压测:识别压测流量,将流量转发到压测分区,隔离正常业务
  • 影子表:识别压测流量,缓存和存储将压测数据落入影子表/影子区域,不影响正常业务
  • 监控:压测流量、业务流量,分开监控

全链路压测,除技术挑战外,在团队协作上,还有两个难点:

  1. 全链路流量梳理汇总:

    1. 全链路发压的时候,并不是各压各的,而是需要一起梳理发压流量。比如春晚营销自己压测的时候,需要压5个接口,但是全链路的时候,有3个接口是被上游系统调用的,就不需要营销自己发压,只要接受上游服务的压力就好了。
    2. 对齐压测方案,比如单机房发压,要保证压同一个机房等。
  2. 压测时的统筹把控:

    1. 全链路压测涉及多个团队,几十个系统同时压测,因此需要整体统筹,分配每人的职责,包括发压,看监控等,一旦出现问题能快速发现,及时停止压力,联合定位问题。

纯查询单机房改代码线上压测

该方案是通过机房隔离,改代码上线到不承接线上流量的单机房,链路梳理,mock掉不可接受的下游第三方服务、mock掉造成写操作的逻辑,构造词表或引流进行压测。

目前我们大部分系统的查询接口线上压测,都是用这个方案。

虽然看上很安全,但是还有不少风险,主要体现在:

  • 下游系统风险:虽然被压系统与在线业务做了物理隔离,但该系统的下游通常也是真实线上环境,所以有很大的第三方风险。
    • 解决思路:梳理整体链路,压测时提前通知下游系统,尤其是公共服务,可根据情况mock一些下游服务;
  • 写操作梳理遗漏:
    • 该方案的前提是纯查询类的请求,需要业务梳理所有被压的接口,确保没有任何写操作,否则会引入脏数据。但实际上,我们很难梳理全一个接口和他请求的所有下游服务都没有写操作,一旦漏掉,就会带来线上脏数据。
    • 几种典型的容易漏掉的写操作:
      • 缓存,查询接口通常都有缓存,如果压测时不注意,可能写进去的脏数据又被读到,影响线上;
      • 统计BI类的数据,通常不在业务逻辑里,通过埋点或者日志来提取,很容易漏掉;
    • 解决思路:①梳理业务时,尤其注意这两类操作;②尽可能的使用内部同学账号,这样万一出现问题影响还可控;
  • 切流量不干净:
    • 部分模块链接入口不规范,可能导致切流量切不干净
      • 解决思路:检查切流量后的机房,确保无线上流量,尤其是要单机房上线改造代码的时候,保证不能影响到没切干净的流量。
    • 切流量,目前只能保证最上层被压模块切到单机房,如果没有”智能流量转发平台”(优先访问相同机房的机器,若访问失败再访问其他机房),下游业务的流量是切不走的,这种其实没有很好的解决下游模块的服务不可用风险。
      • 解决思路:被压测的所有系统都通过”智能流量转发平台”,流量低峰期压测,以减少服务不可用风险;
  • 上线导致mock代码失效:
    • 这个问题在春节红包压测过程中就出现了,原本mock掉了下游发短信,但是因为压测过程中其它rd上线,覆盖了压测代码逻辑,导致压测流量请求了真实第三方,引起问题。
    • 解决思路:
      • 这类风险在所有需要改压测代码的方案都存在,我们一定要规范压测流程, 周知到所有人这段时间不能上线;
      • 尽可能的使用内部同学的账号,多重保障。

利用待上线/ 扩容系统进行线上压测

该方案算是类线上压测,在条件允许的情况下,利用待上线或者扩容的环境进行压测,通过构造的词表或者线上流量录制的词表进行发压,进行容量评估/瓶颈定位&解决,最终来保障活动稳定进行。

该方案相对安全,但是还是有一定风险,主要体现在:

  • 下游系统风险:虽然被压系统是待上线或者扩容的环境,但该系统的下游通常也是真实线上环境,所以有很大的第三方风险。

    • 解决思路:梳理整体链路,压测时提前通知下游系统,根据情况mock一些下游服务;
  • 数据风险:

    • 通常压测待上线系统都有写接口压测,而且是通过上线前清理数据的方式避免脏数据影响。但是这里还有三个风险:
      • 数据清理不干净,可能因为漏清部分数据导致影响线上;
      • 连错数据库,通常我们预期连到扩容的数据库进行压测,但是一旦连接错了,连到线上,就会污染线上数据;
      • 数据清理过快,导致数据库占用资源过高,影响线上;
    • 解决思路:一定要在压测的时候反复检查是否连对数据库,并且压测数据和线上数据隔离双重保证,清理数据时一定注意清理速度。
  • 环境不稳定风险:

    • 这个也是待上线系统独特的特点,因为没有线上流量,系统rd自运维,或者出现上线不规范的情况,这样很可能将压测特殊的代码或配置覆盖掉
    • 比如:上线导致mock的第三方服务或数据库链接配置失效。
    • 解决思路:每次压测的时候都一定要检查diff压测改造代码和配置。

写流量数据隔离+清库线上压测(类影子库)

该方案是通过与在线业务隔离的压测数据,真实压测线上系统,事后清理压测脏数据。

比如:压测红包活动使用特殊号段userId,发券压测使用压测账号发测试券,事后清理脏数据。

该方案风险大,属于高危方案,风险是:

一旦失效,影响线上用户,资金安全,或污染线上数据,甚至导致在线业务不可用

解决思路:多重保证避免

  1. 压测流量标记,透传;
  2. 压测账号隔离等,一定要反复检查请求是否符合预期,线上逻辑处理是否符合预期;
  3. 在压测工具和线上代码中添加校验检查,比如:压测流量不在指定数据范围内的流量拒掉。结合业务做风险分析,多重机制保证。

异步流量堆积发送线上压测

方案是:通过配置化控制缓冲池的消费速度进行压测。

最大的好处是,完全不增加额外的线上流量,使写操作的数据风险降到最低。

该方案最大的风险是:线上服务可用性,主要体现在两点:

积压释放的流量本身的可用性:

因为是积压释放,在大压力下可能导致服务异常处理失败,而失败的这部分流量是线上真实用户的,这样会降低系统的可用性。

解决思路:重试 or 补单 or 对账来解决;

对线上服务可用性:

可能会将系统压挂(原因是:通常写服务,数据库是无法切机房的,所以一旦堆积的流量把服务压挂,会严重影响线上)

解决思路:业务低峰期进行,以减轻风险。

全链路压测方法论总结

标准化流程

明确压测目标,压测前、压测中和压测后的各个环节的checklist,是做好全链路压测的标准化流程。

核心流程和注意事项

该核心流程描述了要做一次线上性能测试,整个过程中在什么时间点要做什么事,照着这个流程能保证我们线上性能测试能够有序且不会遗漏重要的东西。

风险评估&解决方案

线上压测,就会对在线业务有影响,风险评估及解决方案总结:

典型性能问题总结

结合项目,压测遇到,较典型的性能问题,见下:

redis

  • 压力不均衡,有热点:构造的key总会落到一台机器上,形成热点(出现场景有:统计结果集中过期、统计设置过期时间、压测的统计词表、频繁读一个队列数据)–解决方法:key值打散

  • 压力只在8000端口上,cpu使用率很高–解决方法:一是通过域名使用多端口访问,二是使用proxy,BGW或VIP方式,将压力打散;更推荐第二个方案;之前出现过域名平台低版本导致转发不均衡的问题。

  • cpu0核打满–解决方法:一是开启网卡多队列优化;二是扩容

  • 内存达到80%–解决方法:一是修改程序,部分业务功能迁移到别的redis集群;二是扩容

应用

  • 队列积压–解决方法:一是增加消费线程数,或改为批量处理;二是扩容,增加消费模块的机器;三是增加开关控制,仅活动事件不入上述队列。

  • 模块间采用http调用方式耗时长–解决方法:改为nio方式调用,耗时节省约

  • 前置校验补全规则分析,高压力下耗时长,单机3000qps耗时170ms–解决方法:若非必要流程可去掉,活动请求不过校验补全规则。

  • 系统开关控制查redis或DB的功能,高压力下配置成查redis,会提升系统性能。

  • 多个任务处理共用一个线程池,导致任务积压影响性能或其他业务–

  • 规则引擎耗时长

  • youngGC,fullGC次数多且耗时长,影响性能

  • 凌晨切日志或有定时任务,影响性能

  • 因机器问题导致系统雪崩:一台机器性能差,报警无可用连接后,平响瞬间升高,一系列连锁反应,会拖垮应用–解决方案:通过逐步升高压力,摘掉报出无可用连接的机器

  • 联合其他业务压测:词表影响在线业务,及变量传默认值,需改造后压测,否则影响压测效果;压测结束后恢复需求状态。

稳定性&健壮性

  • 开启重试判断后,系统出现雪崩;一般高压力活动场景,不会增加重试机制,会大大影响性能。若有重试,系统应防范雪崩发生。

  • 压力超过一定范围后,持续压测出现模块挂掉,耗时瞬间升高情况–原因:一是规则引擎耗时长,二是机器问题。

  • 高压力下频繁操作起停规则,耗时瞬间上升

  • 多个任务处理共用一个线程池,导致任务积压,影响其他业务–解决方法:一是各个任务间线程池隔离;二是活动机器和在线业务机器全部隔离;三是监控本地队列,数据有积压则报警

压测工具问题

  • 压力不稳–原因有:一是连接的redis跨机房、二是达到发压力极限,发压机器cpu打满;目前单机发压可达5kqps。

  • 压不上去–可调整slave个数,单机一般配置6个slave没问题。

  • 压力工具监控,压力超过一定范围后,qps计算不准