作者:许筱燕
部门:业务中台/测试开发
一、流量回放介绍
1.1 流量回放是什么
流量回放是系统重构、拆分、中台化时重要的自动化回归手段。通过采集可录制流量,在指定环境回放,再逐一对比每个调用和子调用差异来发现接口代码是否存在问题。因为线上流量大、场景全面,可以有效弥补人工评估测试范围的局限性,进而降低业务快速迭代带来的风险。流量回放的整体流程图如下图所示。
1.2 有赞流量回放平台介绍
有赞流量回放平台是基于jvm-sandbox-repeater做的二次开发。通过AOP在运行期无侵入式(业务系统无感知)录制接口入参/返回值。同时可以录制子调用的入参和返回值,子调用类型包括dubbo、mybatis、redis等。因此在支持读流量回放的基础上,可以支持写流量的mock回放。整体架构如下图所示。
下面详细介绍下有赞流量回放平台的两个模式,读模式(pre环境读接口非mock回放)和写模式(qa环境接口mock回放)。
1)读模式:
录制阶段:
- 获取dubbo入口请求、返回值;
- mybatis/hbase增强点判断是否有写入操作,给写操作标志位赋值。
回放阶段:
- 获取所有的黑名单接口、白名单接口,以及当前时间生效的replay任务,黑名单接口不会在预发非mock回放,避免脏数据;
- 根据流量中写操作标志位自动补充黑名单,避免人工配置黑名单造成的遗漏;
- 泛化调用预发环境,判断泛化调用返回值是否和录制一致(支持根据配置自动忽略某些字段);
- 不一致,请求两次生产环境,判断出噪音路径;
- 再次比对预发泛化调用返回值和最新生产环境返回值;
- 回放失败落用例,任务结果记录;
- 回放成功,根据任务配置中是否有蓄流配置,如有且符合落用例规则,那么把流量落成用例;这部分用例后面可以根据实际需要随时在预发回放。
2)写模式:
录制阶段:
- 在请求dubbo入口生成唯一id(traceid),通过唯一id关联这次请求所有的子调用;
- 每个增强点方法执行之前,记录请求,方法执行之后,记录返回值;
- dubbo执行结束,通过唯一id获取此次调用详情,异步序列化后发送nsq。
回放阶段:
- dubbo泛化调用,把录制阶段的traceid放入dubbo的attachment;
- 在dubbo执行入口,根据dubbo的attachment中traceid获取此次调用涉及到的所有子调用;
- 在每个子调用执行之前,根据子调用的类型、类&方法、入参信息,来匹配第一步拿到的所有子调用信息,如果一致,构造返回值进行mock;如果不一致,构造异常抛出;
- dubbo泛化结束,异步发送子调用mock详情到后台;
- 比较泛化调用返回值和录制阶段dubbo返回值。
二、流量回放在中台营销业务的应用
2.1 中台营销业务的特点
中台营销是有赞营销业务的基石,涉及丰富的玩法和众多组合场景。众多活动的优惠价格计算,再加上复杂的叠加互斥规则,很容易造成场景遗漏,甚至造成资损。且伴随公司业务的快速发展,为了更好的支撑业务的迭代,提供更稳定、更高效的中台能力,业务架构重构迫在眉睫。如何在项目中快速回归现有业务逻辑,尽可能广的覆盖测试范围,在计改项目中减少重复性的测试成本投入同时保证高质量的项目上线质量,流量回放成了主要的自动化回归测试手段。
2.2 我们是如何使用流量回放的
首先分析业务分布以及核心场景。营销业务主要在商家端(B端)和消费者端(C端)。B端主要涉及营销活动的增删改查。C端主要涉及各营销活动在微页面、商品详情、购物车、下单链路的营销氛围透出和价格计算,及各活动参与抵扣记录。其次,核心链路的价格计算肯定是第一优先级的。因为营销C端链路有一大部分是活动氛围透出和价格计算,涉及的是读接口。因此第一步完成了读接口的流量回放覆盖,共接入应用19个,接口170+。营销业务大览及流量回放覆盖情况如下图所示。
2.3 遇到的问题及解决
从上面的分析可以看到,营销大部分的读接口都已经覆盖到。但是在实际的使用过程中发现,虽然录制回放了很多流量,但是这些流量到底覆盖了哪些场景是无感知的。因为看不到覆盖情况,无法完全信任流量回放,流量回放似乎是在盲测。另外一个点是受限于流量回放的采样率问题,很多小流量的场景很难被采集到,那么流量未覆盖的场景就会演变成不可预知的风险。
要解决上面的问题,首先需要明确在中台营销的各个接口中什么是场景,哪些特性可以定义为一个场景。从大的角度来说,一个接口就可以是一个场景,比如某个营销玩法的活动列表接口就是一个场景。从更加细致一点的角度,每个接口核心入参或者返回值就可以是一个场景,比如商品详情页接口入参中的店铺类型,返回值中的活动类型。基于此,我们将中台营销的核心接口的主要场景定义分为如下图几个部分:
当然业务中接口众多,不可能详尽地列举每个接口的场景定义。 每个接口可以根据实际的接口定义和功能,自己定义场景。
1)场景覆盖结果可视化
场景定义好之后,将定义好的场景录入到流量回放平台。在平台上,每个场景用一个标签来表示。标签类型是接口或者参数,具体值是接口全限定名或者参数的jsonPath路径。当本次流量回放完成后,会统计出来当前接口的场景覆盖情况,同时标明该场景覆盖的次数。通过场景覆盖的次数这个指标可以在一定程度上透明化流量回放的覆盖情况,增加对流量回放覆盖率的信心指数。如下图是某个应用某次流量回放的覆盖情况。
上图详细展示了该应用当次回放覆盖、未覆盖的接口,整体覆盖和未覆盖的场景。更加详细的,可以选择某个接口,展开该接口的场景具体覆盖详情,如下图所示。
2)小流量场景怎么解决
这里主要考虑了两种方式解决。第一种是通过人工构造指定场景来补充,可以在预发环境构造某些特定场景的请求,将这部分流量保存下来,然后在需要的时候回放。这种方式存在的问题主要是流量的录制和维护都需要花费时间,对测试资源的会有一定的耗费,尤其当需要补充的场景比较多时,管理成本也会比较高。因此考虑到了另外一种解决方式,通过在业务代码中嵌入一部分逻辑,将小流量场景主动上报到流量回放平台。这种方式的缺点是对业务代码有一定入侵,优点是不需要人工录制和维护流量,减少人力成本,且小流量场景也能采集到较为丰富的流量。基于此,在中台营销,主要选择的是第二种方式来解决小流量问题。其流程图如下图所示。
2.4 流量回放在项目中的实际使用
目前流量回放已经在多条业务线有了很好的实践,尤其适用于技术改造项目。这里重点介绍商品详情页营销重构项目中流量回放的使用。
商品详情页承接大量营销活动,几乎所有的营销活动都会在商品详情页透出。同时,当商品参与多个活动的时候,需要根据叠加互斥规则计算出最优的一个或者多个活动叠加后的价格。计算逻辑复杂,导致重构测试回归场景多,且很容易造成场景遗漏。常见的质量保障方式是接口测试+功能测试。测试数据构建、维护,测试脚本编写、维护,功能用例编写、执行都会非常耗时。如果按照这种方式,测试量基本以月计。因此主要使用流量回放来保障项目质量。具体测试方案如下图所示。通过流量回放,该项目在未投入测试人力的情况下,项目上线后未产生任何故障。
三、未来展望
在接入场景方面,目前因为时间、资源等原因,写接口接入有限,但是写接口涉及很多资损逻辑,因此后续需要梳理核心写接口并完成接入。另外,目前只有小量核心接口使用了小流量主动上报功能,且是在接口中硬编码实现的,其他接口想要使用这个功能的成本会比较高。后续计划通过抽象功能,并通过标签标记的方式实现快速接入,减少开发成本。同时,目前的小流量场景都是通过接口入参和出参来定义,比较粗糙,无法覆盖到代码分支、行维度的场景。后续可以结合jacoco来分析覆盖情况,从而补充颗粒度更细的场景。在使用场景方面,因为流量回放是将线上流量采样导入到被测环境,如果采样率足够大,就可以对被测环境进行性能测试。自然地利用生产环境海量真实场景,减少了性能测试数据的准备成本。在数据安全方面,流量回放需要对接口返回的敏感数据进行加密,避免敏感数据泄漏。