作者简介
- 伍菊红,来自货拉拉/技术中心/质量保障部,主要负责营销活动相关质量保障以及流量回放开发工作。
- 史浩,来自货拉拉/技术中心/质量保障部,主要负责交易引擎相关质量保障以及流量回放开发工作。
货拉拉是一家正在快速发展的公司,在业务不断丰富的同时,对技术部门所带来的是快速迭代的奔跑和越来越复杂的业务链路,服务稳定性和人效均面临巨大挑战。初期都是通过补齐接口自动化这种传统模式保障,该模式虽然简单便捷,但存在成本高、覆盖场景有限、标准化难度高等问题。基于此,我们希望搭建一个流量回放平台,利用海量的流量自动构建丰富的测试场景保障测试范围和节省人力。
流量回放是一种通过复制线上/测试环境的实际流量 (录制),然后在测试环境中进行模拟请求 (回放) 来验证代码逻辑正确性的方法。目前,市面上有许多开源产品都提供这种功能,其中包括阿里开源的工具 jvm-sandbox-repeater,基于 Go 语言的 GoReplay,以及 TcpXCopy 等。考虑到我们公司主要技术栈还是以 java 为主,并且我们注意到一些公司,如 vivo、得物、酷家乐等,都在使用 jvm-sandbox-repeater,综合考虑,我们决定选择 jvm sandbox repeater 作为我们的底层框架,来设计货拉拉的流量回放平台 LLRepeater。
接下来将为大家展开介绍流量回放体系在货拉拉的平台设计、实现、挑战以及效果。
平台设计共有以下 5 大块:
插件管理-负责插件的安装、卸载、心跳、启动、冻结、配置推送等一系列与 jvm sandbox agent 相交互的事情;
流量中心-打造流量库,提供流量查询、存储、分析、构造等一系列功能,为自动化、压测模型等赋能;
录制服务-负责录制流量存储、打标、过滤等相关工作;
回放服务-负责实时/手动/自动回放/回放速率/回放结果汇聚等工作;
对比服务-负责降噪配置,结果比对,diffy 分析等;
核心功能共有以下 3 大块:
挂载-控制台下发挂载命令至被测服务,挂载命令会触发 jvm sandbox repeater 挂载;
录制-agent 录制流量转发至控制台,控制台将流量转发至录制 kafka,录制服务消费该消息流量存储至 es;
回放-发起回放,回放结果转发至控制台,控制台将流量转发至回放 kafka,回放服务消费该消息,再调用对比服务进行比对降噪,处理结果存储至 es&db;
货拉拉的业务种类非常多,各个部门使用姿势也不尽相同,为适配现有业务,插件需要不断进行适配,目前已经适配插件如下:
组件类型 | 描述 | 录制 | 回放 | 入口流量 |
---|---|---|---|---|
http | http 请求 | ✅ | ✅ | ✅ |
rpc | 自研 rpc 请求 | ✅ | ✅ | ✅ |
apollo | 服务配置组件 | ✅ | ✅ | ❌ |
feign | easyOpen 组件 | ✅ | ✅ | ❌ |
ibatis | ibatis 组件 | ✅ | ✅ | ❌ |
mybatis | mybatis 组件 | ✅ | ✅ | ❌ |
redis | redis 组件 | ✅ | ✅ | ❌ |
lala-redis | Lala redis 组件 | ✅ | ✅ | ❌ |
guava-cache | guava 缓存 | ✅ | ✅ | ❌ |
en-cache | ehcache 缓存 | ✅ | ✅ | ❌ |
caffeine-cache | caffeine 缓存 | ✅ | ✅ | ❌ |
kafka | kafka 组件 | ✅ | ✅ | ✅ |
系统在初期推广频繁触发 Full GC,服务超时等问题,经过分析主要有以下几点原因:
部分子调用反复被调用,比较明显的是配置中心 apollo 以及 guava cache 这两个子调用,单条流量中相同请求多达 10 次以上,这样的流量一旦过多,会导致内存中大对象变多,容易触发 FULL GC;
序列化对象偏大,存在部分非业务代码导致的序列化字节数特别大的请求,如服务发现等;
针对这些问题,进行了如下优化:
1)apollo 以及 guava 重复请求只录制一次;
2)非业务代码导致的序列化字节超大的请求,skip 掉;
3)对录制过程进行监控/异常降级;
流量回放的主要优势在于能够收集线上的真实流量,然而在生产环境中收集流量时,会遇到两个问题。首先,由于服务的 qps 很高,全面收集流量可能影响业务服务的性能,也会造成资源浪费 (存储一堆流量),其次许多流量都是重复的,这些重复流量对业务测试帮助不大,全面收集并没有太大的意义。因此,生产采集流量,全局采样率配置一般不会太高。但是这种模式可能导致大部分收集到的流量都来自于 qps 较高的接口,而请求量小的接口很难被收集到。为了解决这些问题,我们采用接口维度进行流量录制的配置,具体措施如下:
1) 录制不均:支持接口配置,接口优先级高于全局采样率,可以灵活调整各个接口的比例;
2) 筛选困难:可以从多个维度,针对单条流量进行打标,方便用户筛选出自己需要的流量;
流量回放老大难的问题就是排查成本高,整个录制和回放都是非常复杂的过程,特别是碰到一些子调用高达上百条的流量,回放失败后,使用者无从下手。为了提升排查效率,我们也做了非常多的事情:
与公司的监控链路打通,可以查看整个录制以及回放 trace 链路;
agent 优化,子调用排序,回放详情会打上对应的 match 标签,方便用户找到排查的入口;
批量详情支持按失败原因汇聚,减少重复排查;
常见失败排查策略推荐,领头羊培养等;
为了更方便用户使用,平台设计重点主要围绕"使用成本"、"有抓手"、"能力多样化"、"智能化"等多个角度展开,
接下来将从平台优势和特色效果来展开阐述:
1) 平台优势
接入成本低:从接入、配置、录制、回放整个过程,新手大概 30 min 内完成;
使用便捷高效:流量支持多规则打标、智能降噪、回放结果汇聚等能力,降低排查成本;
结果透明化:与公司覆盖率打通,智能生成回放报告;
个性化支持:支持定时、实时、手动等多种回放姿势;
2) 平台特色
自动回放
自动回放是指针对只读接口,采用手动/定时触发的方式,使用实时录制的指定/随机流量进行非 mock 的降噪回放,汇总结果数据,进而实现 “0” 测试人力成本完整的查询接口测试。此方式误报率极低,不用担心代码链路变动用不了,也能更全面的覆盖线上场景。
链路回放
在多个大型核心系统架构升级背景下,基于现有单服务录制能力、货拉拉全局 Trace 能力、业务场景代码插桩能力,与研发团队共建了链路级流量回放能力,经过重构项目的应用,链路录制回放探索落地已取得初步胜利。
接收外部流量输入并在平台内进行回放
当前的流量录制与回放仅支持 java 系统,但对于服务语言(其他语言转 java)重构的项目,此平台就无任何用武之地。为了能在此种项目中发挥效果,故将平台本身的录制模块进行灵活化改造,可以录制 java 服务流量,也可自定义流量输入。
流量回放虽然具备自我录制和回放的完整能力,但因微服务的大流行,后端架构变的越来越复杂,市面上很多公司都没有有效的应用起来,原因主要有 2 个:
非 mock 回放的好处在于它不会受代码链路变更影响,但此种方式需确保录制与回放处于同一环境内、共用底层存储并不能变更数据,也就是指在同一环境内对读接口进行录制与回放。此种应用类型的失败只有一种,即返回值差异,降噪处理起来十分清晰与简易。目前平台共支持 2 种模式,java 录制 java 回放、php 录制 java 回放,可进行手动/自动回放。
累计回放次数 5k 次,流量数 60w+,拦截问题200+。
mock 回放的弊端是受代码链路变更影响和验证不到底层中间件部分,所以它比较适合技术架构比较稳定的业务线。基于此分析我们在具有此类业务线特性的团队进行推广应用,串入到项目流程的准入(提测)和准出(回归)环节使用。
累计回放次数 1k 次,流量数 10w+,拦截问题10+。
链路回放的接入成本较高,主要耗费在业务场景代码插桩上,但它很好的补充了单服务录制回放的短板,适合于大型链路升级与重构。
此能力目前应用于货拉拉的一个大型核心履约链路架构升级项目,拦截问题180+,协助项目做到万无一失。
经过长期的迭代优化,我们已经在 3 种不同的应用(非 mock 回放、mock 回放、链路回放)取得了阶段性的正向收益,这使我们能更好地应对业务快速迭代和系统架构升级的挑战。对于下一个阶段目标,主要从高效、流程管控、智能、拓展四个方面展开。
公司已有的精准平台具有能提供每次提测分支受影响的方法以及该方法影响到的所有接口的能力。此能力可帮助 LLRepeater 进行精准回放无需人工介入,这样无论是对资源还是人力成本上都具有提效的效果。
需要完善流程管控,未来将会与公司的准入准出流水线进行结合,避免受人的影响,导致执行不一的情况发生。
基于回放对比知识库的数据沉淀,利用智能化技术帮助使用人员分析解决问题,降低使用门槛,吸引更多的用户。
Java 是目前后端架构的主流语言,但是像 go、php 等语言也有很多,未来会在 LLRepeater 上兼容更多语言,做大做强。