一、为什么要应用流量录制与回放?
1.1 vivo 业务情况
近几年,vivo 互联网畛域处于高速倒退状态,同时因为 vivo 手机出货量始终在国内名落孙山,通过多年积攒,用户规模十分宏大。因而,vivo 手机出厂内置很多利用,如浏览器、短视频、直播、资讯、利用商店等都是直面用户的高并发、简单零碎。这些面向用户的系统对应用体验要求十分高,对这些业务的品质保障是重中之重。
1.2 测试痛点
随着咱们业务规模和复杂度一直进步,各种问题和挑战随之而来。其中“在业务迭代降级甚至重构时,如何保证系统批改后的原有业务正确性?”是咱们正在着手解决的其中一大难题。
简略的业务零碎通过惯例的自动化测试工具加上人工测试即可解决,对于简单零碎,回归测试将变成一项艰巨的工程。以咱们举荐零碎为例,一个举荐零碎承当了数十个举荐场景。如何在批改某个举荐场景的状况下保障不影响其余场景呢?
之前,咱们是通过编写自动化测试用例去解决,然而通过人工编写的测试用例存在较多痛点:
- 测试用例编写难,数据结构难,用户实在的应用行为不容易模仿。
- 局部代码逻辑通过测试脚本难以验证。例如发送音讯无奈验证音讯内容没有问题。
- 依附人工结构用例难以思考到零碎所有场景,容易造成用例脱漏。
- 随着零碎部署复杂度回升,环境保护老本也比拟高。
针对这些简单业务零碎在迭代过程中回归测试效率低的问题,咱们进行了一些持续性摸索。
1.3 计划摸索
咱们联合 vivo 互联网体系特色对业界一些计划进行了宽泛调研和参考并列举了如下要求:新计划要能简略高效,用户无需过多了解就能轻松上手;业务接入老本足够低,可能疾速进行回归测试;新计划通用性、扩展性要足够好,能适应一直变更的零碎架构。
咱们参考了一些头部互联网公司的技术计划,发现流量录制与回放是一个十分好的抉择。业界内有不少头部公司基于这种技术获得了不错的停顿和落地价值,为咱们带来了一些参考和信念。因而,对于流量录制回放,咱们进行了一些更加深刻的摸索和落地,也就是咱们的月光宝盒平台。
二、什么是流量录制与回放?
在介绍具体实际之前,先简略介绍一下什么是流量录制与回放?
流量录制回放是通过复制线上实在流量(录制)而后在测试环境进行模仿申请(回放)验证代码逻辑正确性。通过采集线上流量在测试环境回流放一比照每个子调用差别和入口调用后果来发现接口代码是否存在问题。
利用这种机制进行回归测试具备许多劣势:首先,通过录制流量取代测试用例简略高效,易于造成丰盛的测试用例;其次,回放线上流量能完满模仿用户实在行为,防止人工编写存在的差异性;另外通过对录制数据和回放数据采纳对象比照形式能更深刻、轻微验证零碎逻辑;最初录制的流量无需保护,随取随用,十分不便。
三、月光宝盒平台
流量录制与回放这种创新性的机制实践上是十分优良的,然而实现起来却不太容易,外面有诸多难题须要解决。上面将给大家介绍流量录制与回放在 vivo 互联网体系的落地计划和遇到的问题以及咱们是如何解决这些问题的。
3.1 底层架构
vivo 月光宝盒平台借鉴了开源 Jvm-Sandbox-Repeater 我的项目教训,在 Jvm-Sandbox-Repeater 根底上做了二次开发和革新。月光宝盒平台包含了服务端和 Java Agent 两大模块,整体架构如下图所示。
3.1.1 业务架构
下图是咱们服务端整体业务架构,整个服务端能够划分成工作治理、数据管理、覆盖率剖析、配置管理、监控告警等模块。
- 工作治理模块治理用户的录制和回放工作,包含工作启停、工作进度、工作状态等;
- 数据管理模块用来治理用户录制与回放的流量数据、以及剖析数据;
- 覆盖率剖析模块用来统计用户回归覆盖率指标;
- 配置管理模块用来配置零碎与利用的全局参数;
- 监控模块用来剖析 Agent 各方面性能指标;
此外还有一些音讯告诉模块。
3.1.2 Agent 架构
下图是 Agent 模块整体架构图,Agent 是流量录制回放过程的外围。Agent 是基于字节码机制实现,整体包含了四层构造:
- 底层是根底容器层,这一层是规范的 Java-Agent 实现;
- 容器层下面是依赖层,这一层引入了咱们须要的第三方资源、实现了字节码插桩机制、类加载隔离、class 元数据管理能力。
- 依赖层之上是根底能力层,在这一层实现了根本的原子性能,如录制回放插件的治理、数据管理、数据比照、子调用 Mokc、运行监控、配置加载等能力。
- 最上层是业务逻辑层,这一层能够将根底逻辑性能组合在一起造成一个残缺的业务单元。目前月光宝盒除了反对流量录制与回放外,还反对了相似依赖剖析、数据 Mock 等性能。
3.2 月光宝盒的启动流程
录制回放工作启动最重要是能无侵入的将咱们 Agent 下发到指定业务机器上并且主动将 Agent Attach 到咱们业务过程下来。
月光宝盒的启动流程如下图所示,用户首先在月光宝盒平台配置录制回放工作。实现配置后,配置信息会入库并同时通过 VCS(vivo 自研的作业调度平台)将启动脚本、vivo-repeater-agent 包下发至用户配置的机器上。而后会执行 shell 脚本并拉起 sandbox,将 agent attach 至指标的 JVM。随后 agent 便能够在指标 JVM 上通过反射创立 jvm sandbox,sandbox 会通过 spi 拉起多个模块。
其中最重要是 vivo repeater module,它会通过 spi 加载多个插件,这些插件最终会以 ASM 的形式加强指标 JVM 上的代码,从而实现字节码插桩,而流量的录制与回放便是应用这些加强的插件进行流量拦挡、下发存储实现的。
上述的执行流程容许用户仅凭在控制台配置大量信息就能实现简单的流量录制与回放性能,上面咱们将对录制与回放的具体过程进行阐明。
3.3 流量录制过程
上面是一个流量录制的过程。一条流量的调用链路包含入口调用和若干次子调用,流量的录制过程就是把入口调用和子调用通过一个惟一 ID 绑定成一次残缺的调用记录。月光宝盒找到入口调用和子调用适合的代码点(要害入口和进口),基于字节码插桩技术在该代码点进行代码加强,实现调用拦挡,记录调用的入参和返回值,而后依据相应的调用类型(如 dubbo、http)生成一个录制标识。当调用实现时,月光宝盒就采集到了整个流量的调用记录,之后月光宝盒进行数据脱敏、序列化等操作,最初加密发送到服务端进行贮存。
录制是一个比较复杂的过程,在这个过程中咱们继续踩了一些坑和遇到了一些问题,上面我列举几个比拟重要的问题和大家分享一下。
3.3.1 难点一:Full GC
初期,vivo 外部零碎在应用月光宝盒时产生了 Full GC 的景象。通过剖析得悉是录制的接口对 guava 调用十分多,导致录制的申请流量太大从而造成了 FULL GC。这是因为在实现一条接口流量的录制前,录制到的所有数据都在内存中,流量或者子调用一旦过大便容易导致频繁 Full GC。另外还有一些高并发零碎接口比拟多,同时录制多个高并发接口存在性能压力。因而,咱们过后针对月光宝盒的性能问题进行了如下优化:
- 严格限度并发录制数量、限度单条流量子调用数量;
- 对录制过程进行监控、异样降级;
- 合并雷同的子调用录制过程以缩小子调用数量。
- 对录制缓存占用进行实时监控,超出警戒线及时进行降级解决。
通过一直优化后,录制过程十分安稳,再也没有呈现因为流量过大或者其余问题导致的 Full GC 景象。
3.3.2 难点二:调用链路串联
流量录制和回放存在线程上下文标识,vivo 有不少零碎有自定义业务线程池或者应用第三方框架自带了线程池(例如 Hystrix)会导致标识失落导致无奈串联整个调用链路问题。
月光宝盒最开始是依赖 Jvm-Sandbox-Repeater 的根底能力,在未应用线程池时,能够将录制标识寄存于 ThreadLocal 中串联整个调用链路;而应用线程池时,咱们利用自身 Agent 对 Java 线程池进行主动加强透传咱们录制回放标识,但这么做会和公司的调用链 Agent 对线程池的加强产生抵触从而导致 JVM 异样解体,这种形式没有方法进行。
最终咱们决定与公司调用链团队单干,借助调用链的 Tracer 上下文进行传递录制标识,单方都进行了肯定水平革新特地是两个 Agent 对 HTTP、Dubbo 埋点地位进行了肯定调整。目前咱们还没有解决 ForkJoinPoool 这种线程池框架传递标识问题,后续会持续对这类线程池做反对。
3.3.3 难点三:数据安全
第三个是录制的流量如何保障数据安全,不少零碎有一些铭感数据。对此,咱们针对录制的数据进行了可配置化的脱敏解决,用户能够在月光宝盒平台配置待脱敏字段,Agent 在录制流量的时候后会依据配置信息在内存中对这些字段进行脱敏解决,保障传输过程和存储过程的数据安全。另外,月光宝盒会严格控制流量详情的查看权限,避免跨我的项目的数据查问行为。
3.3.4 难点四:流量去重
第四个是流量去重问题。有时业务方在应用月光宝盒平台时可能录制到十分多的雷同流量,造成后续回放耗时较长和问题排查效率低下。因而咱们针对该景象思考如何能在保障接口覆盖率的状况下尽可能减少雷同流量的数量。目前的计划是依据流量入参和执行调用栈作去重操作。在录制时,Agent 会依据去重配置信息进行流量去重操作,保障入库的流量数据是惟一的。通过这种机制在一些场景大幅度缩小了录制流量数量,进步了流量的应用效率。
3.4 流量回放过程
下图是流量回放的过程。流量回放是通过获取录制流量的入口调用,再次对迭代后的零碎发动调用,而后去验证零碎逻辑正确性的过程。和录制不一样的是,回放对于内部的调用都是 Mock 的,这个过程不会真正的去拜访数据库。回放过程会将录制子调用和回放子调用的入参进行比照,如果参数不统一那么会阻断回放流量,如果参数统一会应用录制子调用的后果进行 Mock 返回。回放实现同样会产生一个响应后果,这个时候咱们会比照原始录制后果和回放响应后果,依据该比照后果和子调用的比照后果就能得出被测试零碎的正确性了。
回放是一个更加简单的过程,因为录制和回放个别在不同环境的不同版本零碎执行,可能存在较大差别,如果处理不当回放成功率会比拟低。起初接入月光宝盒的利用成功率都比拟低,起初通过长期优化和精细化经营,月光宝盒的回放成功率一直晋升。上面将分享几个遇到的难点以及一些应答策略。
3.4.1 难点一:工夫差别
第一个难点是工夫差别的影响,一些零碎业务逻辑外面存在和工夫无关逻辑,因为录制和回放工夫不一样导致不少场景有工夫相干逻辑导致回放失败。针对这个问题咱们进行了一些钻研,并最终将回放工夫和录制工夫保持一致。
对于 System.currentTimeMillis() 这种 native 办法,Agent 会动静批改办法体的字节码,代理掉业务对该办法的调用,动静替换为平台当时定义的获取工夫办法从而保障工夫替换。解决了这个问题对于 Date 这些类也就迎刃而解了。另外,JDK8 中的 LocalDateTime 等非 native 工夫办法就比较简单了,间接 Mock 掉工夫办法调用即可。应用这些机制基本上打消了业务逻辑外面的工夫差别问题,打消了因为工夫导致的回放失败问题。
3.4.2 难点二:零碎降噪
第二个难点是如何解决零碎乐音。很多零碎外面存在一些 traceId、sequenceId 等通用乐音字段,这些乐音字段也是导致回放失败的因素。初期业务接入时须要一一排查,整体效率比拟低。起初月光宝盒反对了全局级别、利用级别、接口级别的乐音字段配置,很多通用的乐音字段能够间接通过全局配置解决,业务接入只须要个性化配置乐音字段即可,通过这种分档次的降噪配置大幅晋升业务接入效率。
3.4.3 难点三:环境对立
第三个难点是环境差别。以 vivo 互联网体系为例,个别在线上环境进行录制,在测试环境和预发环境进行回放,刚开始因为环境不统一导致回放失败的案例十分多,影响了整体回放成功率。针对这个问题,咱们进行了一系列摸索和解决。月光宝盒在线上录制时会同时录制一份线上环境配置,线下回放时会利用线上配置主动替换掉线下的环境配置,通过这种机制保障了配置核心数据一致性。另外对于一些零碎内存性质的配置数据,月光宝盒反对配置接口同步内存数据。通过这些解决方案,咱们基本上保障了线上、线下环境的一致性,大幅度缩小了因为环境配置导致的回放失败数量。
3.4.4 难点四:子调用匹配
第四个难点是子调用匹配问题。最开始指定的匹配策略无奈满足简单业务场景,经常出现匹不到流量或者匹配谬误导致回放难以胜利。前面咱们针对不同的回放子调用指定不同的匹配策略:缓存类型依照缓存 Key 去匹配;HTTP 类型依照 URI 匹配;Dubbo 依照接口、办法名、参数类型匹配等。另外,如果匹配到多条雷同子调用,咱们会比拟零碎调用栈和入参申请参数,联合调用栈和申请参数两个维度寻找最可能匹配流量,通过这些精细化匹配策略晋升了匹配成功率。
3.4.5 难点五:问题排查
第五个难点是问题排查了,录制和回放是非常复杂的过程,因为 Agent 运行在业务端机器呈现任何问题去剖析排查难度都很大。为了晋升排查效率咱们反对了若干伎俩:
1)、反对回放剖析调用链路图,上面会具体解说;
2)、工作启动具体命令和参数输入,通过输入工作启动命令参数,咱们在本地十分不便启动和模仿线上运行的录制和回放工作,进步了排查效率。
3)、本地一键装置 Agent,在本地批改了 Agent 代码后咱们一键就能够将新的 Agent 在本地近程测试环境装置。
除了这些性能外咱们还开发了很多效率工具,这里就不一一开展阐明了。
3.5 丰盛的协定反对
vivo 业务品种十分多,不同业务技术栈有差别。这些零碎接入咱们平台须要针对性的适配相应插件。通过咱们不断完善插件,目前咱们曾经反对了上面数十种插件,根本曾经笼罩了各种常见的中间件。
3.6 月光宝盒平台其它特点
3.6.1 可视化调用链路
起初,业务回放失败只能依附平台开发人员帮助排查,整个排查过程费时费力。针对这种状况,咱们提供了一些可视化的运维工具。其中一个就是链路调用剖析图。咱们对录制和回放过程进行具体跟踪和记录,通过调用链路图帮忙用户剖析执行过程。呈现问题时,用户能够清晰看到具体异样地位和根本原因,进步了排查效率。
3.6.2 回归代码覆盖率
月光宝盒的劣势之一是具备很高的流量覆盖率很容易造成高覆盖率。如何去验证回放的流量的确笼罩了业务零碎的各个场景,让应用人员应用了月光宝盒就不存在疑虑放心大胆的上线。
针对这个问题,月光宝盒提供了代码回归覆盖率的统计能力,咱们利用外部的 CoCo-Server 平台统计了零碎全量覆盖率和增量代码覆盖率。为了辨认覆盖率数据来自流量回放,咱们在回放前须要调用接口清理机器内存外面的覆盖率数据,这种形式可能存在和其余流量抵触可能性,后续等 CoCo-Server 平台实现流量染色辨别流量起源就没有这方面担心了。
3.6.3 定时录制与回放
尽管流量录制和回放的操作流程曾经十分简便了,但对于一些频繁应用的业务人员来说依然较为繁琐,特地是有些版本波及了过多的零碎,同时录制回放多个零碎效率比拟低下。为了进步应用效率,月光宝盒反对了用户自定义定时录制、回放工作的能力。通过定时工作能够批量定时录制和回放,减小了人工操作老本,进步了平台应用体验。
3.7 月光宝盒其余利用
除了自动化测试,咱们在其余方面也进行了一些摸索和利用。第一个是流量压测,用户能够通过月光宝盒平台剖析录制的流量生成的压测模型。第二个是问题定位,应用月光宝盒平台在线下回放重现线上问题,帮忙测试、开发人员复现问题现场。最初一个是平安剖析,常态化录制测试环境流量能够帮忙平安工程师提供流量素材,辨认业务系统安全危险等。
四、外围指标
月光宝盒平台的接入非常简单,业务首次接入基本上 10 分钟内就能够实现。平台上线不到一年就累计接入了近 200 个业务零碎,很多都是 vivo 互联网体系中最为外围的利用。一年以来累计实现 1W+ 次录制与回放。接入月光宝盒后,平台提前发现了不同业务的累计数十个线上问题,无效缩小线上事变产生次数。在很多场景下,应用月光宝盒平台的流量录制回放性能能够晋升测试、开发人员 80% 以上的工作效率,总体来看超出了咱们的预期指标。
五、将来布局
在将来布局上咱们次要聚焦在两方面,一个是性能布局,第二个是协同开源。
5.1、性能布局
目前咱们实现了平台根底性能建设,然而还存在应用效率等问题,后续咱们重点会在上面两个方向去优化:
1)心愿可能实现精准化测试,防止每次全量回放录制数据,进一步升高回放耗时。精准化测试须要剖析变更代码,取得变更代码的影响范畴,而后基于此筛选出对应的流量进行回放,这样就能减小回放覆盖范围。
2)是心愿可能与 vivo 互联网体系下的 CI/CD 联合,当业务零碎公布到了预发环境后,可能主动触发录制和回放工作。这样在上线前能给零碎进行一些危险辨认同时晋升用户应用效率。
5.2 开源共创
开源是将来软件的发展趋势,对于开源,咱们始终是受益者,咱们也冀望能积极参与到开源我的项目为社区贡献力量。咱们参加了开源 https://github.com/alibaba/jvm-sandbox-repeater 我的项目,成为了社区外围贡献者。第一期累计奉献了 5 个社区没有然而比拟重要的插件。后续咱们筹备持续依照上面布局逐渐向社区回馈月光宝盒的一些外围能力。
作者:vivo 互联网服务器团队 -Liu YanJiang、Xu Weiteng
本文依据 Liu YanJiang 老师在“2021 vivo 开发者大会 ” 现场演讲内容整顿而成。公众号回复【2021VDC】获取互联网技术分会场议题材料。