写点什么

有赞精准测试实践

  • 2019-09-24
  • 本文字数:2847 字

    阅读完需:约 9 分钟

有赞精准测试实践

一、背景介绍

有赞早期业务跑在一个单体 php 工程上,随着业务发展,性能拓展性已经满足不了需求,为了后续发展,底层开始微服务化,整体转向 dubbo 框架。从单体转向分布式框架,测试也面临着一系列问题,如下:


  1. 对于分布式系统中的绝大部分应用,随着业务发展,自身应用代码复杂度会不断增加,如何准确、全面判定代码修改影响范围会越来越重要;

  2. 一些领域设计不太合理的业务架构,会发现任一应用接口变动会使多个应用受影响。测试过程中会发现只是自身应用代码一个修改,会导致对外暴露的接口逻辑发生很大变动,此时测试人员需要判定出这个对外暴露的接口对上层应用到底有多大影响;

  3. 业务快速迭代导致测试时间不断压缩,全量回归是一个很困难的事情,那么测试范围需要开发测试人员根据代码和业务熟悉程度精确把控,风险容易失控;


基于上述背景,我们研发了精准测试工具,作为应用上线质量的参考维度之一,集成到测试工具平台上供技术部门所有同事使用。

二、整体方案设计

对于上面的痛点,可以分为三步走;第一步修改过的代码如何识别,第二步分析出自身应用有哪些接口受到影响;第三步获取上层业务方受到的影响;设计要点如下:


  1. 识别变更的代码:上线代码和 master 代码采用抽象语法树分析,去除噪音后,比对方法体即可获取到新增/修改/删除的方法;

  2. 分析影响的自身应用对外暴露的接口,采用动静结合。静态分析采用字节码分析,同时补充了桥接来解决部分多态问题;动态分析采用了和主流调用链技术一致的 javaagent 来对代码进行织入,为了防止大量织入导致性能变差,只在 qa 环境进行织入;

  3. 对于应用间链路查询,由于有赞内部很早就有一个调用链系统,可以实时查看应用接口之间调用详情,借助这个系统,使用大数据 spark 或者 MR 进行离线任务,汇总处理所有的链路信息即可获取应用间所有链路信息,上层业务方影响范围只要查询链路即可获得。


PS:对于没有现成调用链的公司可以参考成熟的开源工具 skywalking,github 地址如下:https://github.com/apache/skywalking


三、重点模块

重点模块包含了代码比对,静态分析,动态分析,动静结合,应用间影响分析。

3.1 代码比对

设计思路:影响分析,首先需要判定哪些方法发生变动。传统的 git/svn 会把增加的注释、空白字符、空行等非业务代码认为是代码变动,实际上这类变动对于我们业务来说没有任何影响;而单纯判断编译后的 class 文件,是可以避免这些误判,但判断哪些方法发生变动,需要比对方法体的指令,同时还要处理各种内部类的问题,难度不小;为了解决这个问题我们采用了语法树分析,流程如下:


3.2 静态分析逻辑

设计思路


对于 java 代码,分析字节码可以发现,调用方法是通过 invokestatic,invokespecial,invokeinterface,invokevirtual,invokedynamic 这五个指令,扫描每个方法体指令中的 invoke 指令,获得应用内部调用链中的一系列父子节点。每个应用对外暴露出去的接口都可以认为是一棵内部调用链的根节点,从根节点出发遍历可达的所有节点,那么内部调用链即可生成。要点如下:


  1. 对于字节码分析,有很多字节码操作工具,ASM/bcel/Javassist 都可以,使用方法都类似,随便选择一个就行;

  2. 对于 invokedynamic 指令,单纯按照字节码指令指向的是一个引导方法(Bootstrap Method),需要判定真正执行的方法,进而获取真正的调用链;

  3. 为了加快速度,减少后期处理,需要剔除掉不感兴趣的父子节点,比如调用三方包/jdk 的 API/get 方法/set 方法;

  4. 调用接口指令是 invokeinterface 方法,但实际上真正执行的是接口的实现类代码,如果接口只有一个实现类,那么我们就可以判定执行的就是这个实现类,从而可以进行桥接;

  5. 匿名内部类编译过程中会生成一个类似 A$1 的 class 文件,根据字节码文件中的 EnclosingMethod 字段可以判定上层调用方的类名和方法名,从而可以完成方法和匿名内部类方法的桥接;


动态分析 &动静结合

动态分析


对于代码中存在的 AOP 和多态,静态分析无法很好的解决,采用动态分析将会很好的解决这个问题。使用 javaagent 对内部方法进行代码织入,当执行自动化或者功能测试,可以记录一次请求经过的所有内部方法,这样形成的内部方法调用链将会记录 aop 和多态执行的真正的方法,静态的弱点会得到很大的补充。要点如下:


  1. 性能问题:大量织入会导致性能损耗,首先判定当前环境,是否是 qa 环境,qa 环境再织入,不要对线上有影响;

  2. 织入范围:只对 com.youzan 的包进行织入且排除掉二方包(二方包包名一般也为 com.youzan.*),排除掉所有的 get/set 方法,排除掉 private 方法(子类重写不了父类私有方法),排除掉这些会大大加快代码织入速度,且对分析无影响;

  3. 对于每次请求到结束返回,整个调用过程可以看作是不断入栈出栈的过程,调用一个方法是入栈,方法结束为出栈,当栈为空,即表示请求结束,出入栈的顺序反映了代码的调用逻辑,从而形成内部调用链;



动静结合


动态分析会存在样本不足,内部调用链不能完全反映内部方法调用情况;静态分析存在多态和 AOP 的问题,存在孤立的节点,无法串联起来;为了尽可能分析出受影响的范围,以及避免动静分析两种方式的弊端,采用动静结合,要点如下:


  1. 根据动态分析和静态分析,分别获取了一系列内部调用链,把这些内部调用链的节点打散后重新组合得到包含动态和静态数据的内部调用链;

  2. 根据新增/修改的方法名称和方法入参类型,匹配出包含此方法的内部调用链,内部调用链根节点就是改动点影响的对外暴露接口;


3.3 应用间影响分析

应用间链路采集采用的是 sdk+javaagent,整体方案类比 skywalking,可以参考 skywalking 进行二次开发。此处主要介绍离线分析思路,应用间调用链的数据都是每个应用分批上报,一次请求在各个节点上报的都会包含最上层调用方接口、上层调用方接口以及本接口信息,汇总去重后将反映出整体应用间调用详情。(PS:由于一些异常情况,实时上报的链路数据不一定完整,故离线统计入库之前需要判定是否为一棵完整的调用关系树)


3.4 效果

应用内影响的接口效果如下,主要包含了汇总信息/比对页面/影响点对应的接口:



一个接口可能被多个调用方调用,对于开发和测试人员一般最关注的是接口直属调用方和入口调用方以及整体的拓扑图,如下所示:




某些情况下,单条链路调用链详情也需要展示出来:


3.5 不足

  1. 对于新增代码的影响面大部分都是依靠字节码分析,而字节码分析在多态和 AOP 方面存在天然短板,影响面会有所丢失

  2. 应用内链路跟踪存在大规模代码织入,对性能和内存资源会造成一定损耗,对于代码量很大的工程,损耗尤其严重;

  3. 对于大规模代码重构或者底层公用方法的变动,影响面分析会覆盖很多接口,此时依然需要人工评估是否可以缩小测试范围;

  4. 目前应用内代码分析只支持 java 语言,缺少其他语言的范围评估。


本文转载自公众号有赞 coder(ID:youzan_coder)


原文链接


https://mp.weixin.qq.com/s?__biz=MzAxOTY5MDMxNA==&mid=2455760012&idx=1&sn=07ebcab572db3424c502360d96ce79f0&chksm=8c686aa9bb1fe3bf9622b2049a220e5a2ceef86dcbe276dd52423f647900d4c19ca74720879e&scene=27#wechat_redirect


2019-09-24 08:004066

评论

发布
暂无评论
发现更多内容

AbstractFactoryPattern-抽象工厂模式

梁歪歪 ♚

设计模式

架构实战营-模块2作业

Crypto们纷纷聚焦“Building platonic”,PlatoFarm是解决方案吗?

股市老人

跨平台应用开发进阶(十八) :全局异常日志处理方案探究

No Silver Bullet

5月月更 异常日志 处理方案探究

PrototypePattern-原型模式

梁歪歪 ♚

设计模式

西昊智能家具2022新品发布,硬实力为健康撑腰

极客天地

Vue框架学习笔记【day二】

恒山其若陋兮

5月月更

WPF|快速添加新手引导功能(支持MVVM)

沙漠尽头的狼

C# WPF 新手引导

「AuthTalk」今晚 7 点直播|从制造到“智造”,探索制造企业破局之道

Authing

云原生 身份云 制造业 Idaas

从原理到操作,让你在 Apache APISIX 中代理 Dubbo3 服务更便捷

阿里巴巴中间件

阿里云 开源 云原生 dubbo

linux之curl使用技巧

入门小站

Jenkins Agent 的低成本高弹性实践

玄月九

Kubernetes jenkins 弹性 降本 Kaniko

上篇:技术架构的设计方法

阿里巴巴中间件

阿里云 中间件 技术分享 技术思考

密码学系列之:X.690和对应的BER CER DER编码

程序那些事

密码学 程序那些事 5月月更

Angular 项目里使用 scss 文件的一些技巧

汪子熙

typescript 前端 前端开发 angular 5月月更

Docker下RabbitMQ四部曲之四:高可用实战

程序员欣宸

Java Docker Docker-compose RabbitMQ 5月月更

Feign 共享登录信息进行请求

Java Feign

朋友圈架构设计

intelamd

2.4 航线图介绍

Geek_古藤模根

图数据库实战 Gremlin

MSVC编译环境介绍

Loken

音视频 5月月更

在线HTML转Javascript工具

入门小站

工具

OKALEIDO简化玩家进入NFT的门槛,做NFT界的UNISWAP

股市老人

RocketMQ 5.0: 存储计算分离新思路

阿里巴巴中间件

阿里云 开源 云原生 消息队列 Apache RocketMQ

[go]mongo工具类

林逸民

Go mongo goalng-underscore

BuilderPattern-建造者模式

梁歪歪 ♚

设计模式

TreeSet源码分析

zarmnosaj

5月月更

SAP UI5 的自动化测试套件页面的开发步骤介绍

汪子熙

JavaScript SAP SAP UI5 5月月更 SAP前端开发

【安全】揭秘小白如何从0到1逆袭成为安全工程师

网络安全学海

网络安全 安全 信息安全 渗透测试

在线字符或文本转二进制工具

入门小站

工具

下篇:技术 Leader 的思考方式

阿里巴巴中间件

阿里云 中间件 技术分享

微信朋友圈高性能架构设计

地下地上

架构实战营

有赞精准测试实践_文化 & 方法_魏士超_InfoQ精选文章