百度研发过程效能提升

2022-12-03 11:42:12 浏览数 (1)

效能提升,目前业务主流的改进方案集中在流程改进、测试效能提升、发布效率提升等方面,对于占到研发测试周期70%的研发过程如何开展效能提升工作缺少成熟的方案。

百度资深测试工程师陈蕾老师的这篇干货分享,一起来看看!

讲师介绍

陈蕾 资深测试工程师

百度垂类交付效能负责人,在敏捷转型、Devops、云原生提效、效能数字化等方面有实践经验。

以下内容根据陈蕾老师在TesterHome社区与百度主办的测试之美《效能提升实践》主题技术沙龙直播现场所讲内容进行精简整理,大约5300个字左右。

整体规划

首先来看我们的一个业务数据,左边这个图,可以大概看到就是开发周期和测试周期的一个数据变迁。

测试周期经过我们一系列的在测试环节的各种改进,比如像环境流水线自动化建设等等,测试周期其实是处于持续下降的一个状态,也是越来越好转的。但是我们整个开发周期的这个过程,长期以来其实没有很明显的一个变化的。

而且整个测试周期跟开发周期的占比,我们可以看到基本上是达到了大概7:3的一个比例,对于整体的这个业务来说,我们如果想要再进一步的去提升整个业务交付效能的话,如果再持续去做测试环节的这种优化的话,也是逐渐达到一个优化瓶颈的状态。

这个时候可能我们就面临两个选择:

  • 测试环节去挖掘更多的可能性,把各个测试环节做到更极致,来进一步达到提升的目标;
  • 以QA视角介入到研发编码的过程当中,然后尝试去提升这70%的这个量,来扩大我们整个效能工作能够影响到的天花板。

经过一些探讨,进入这个70%的这个领域,在研发编码的这个环节,去做更多的事情,把整体业务的效能做到更优,可能是一个更有价值、天花板更高的事情。在大概去年的时候,我们对这方面去做了一些尝试,也有了一些落地的效果,所以今天主要就是围绕怎么样在整个研发编码的过程当中,作为QA能够去做一些什么样的事情,如何对这个环节的效能做一些改进进行一个分享、探讨。

在做研发过程的这个效能改进,我们先要了解研发在这个过程中到底做了些什么事情以及他们在这个环节里面,到底会遇到什么样的一些困难,会导致他们效率的一些降低,或者导致开发提测延期,占用了70%的这个时间啊。针对我司的情况,大概梳理了3个方面的问题——

编码的方面:

  • 流程相关;
  • 编码格式要求;
  • 绑定需求卡片流程要求;
  • 那对于新人研发来说,需要一个比较长的适应过程 ,然后也会出现反复提交代码、编译代码的一个情况。

研发自测的方面:

  • 环境联通困难;
  • 本地服务依赖比较复杂;
  • 影响范围较难把控,也会导致自测不充分,自测之后问题多等等问题。

联调方面:

  • 联调成本较高;
  • 对接成本高,单方面的修改,对接方需要花较多的人力进行联调配合。

基于以上收集的一些研发环节问题,我们希望可以提供一款在研发过程中能够解决研发同学方方面面的一站式工具。目标就是赋能研发过程来提升开发阶段的编码测试和效率,基于上面的分析,我们把工具箱大概分成了 4 个方面的能力:

  • 流程赋能,提供日程管理、流程辅助,智能客服的一些能力;
  • 开发过程赋能,提供智能编码、代码检索、代码分析;
  • 测试过程赋能,提供环境能力、本地测试、数据;
  • 度量能力,数据采集、个人报表。

工具箱除了提供能力之外,同时也可以解决原来在整个研发过程中数据空白的状态。通过工具箱的形式,研发使用后。我们同时具备了在研发过程中采集研发更细粒度数据的能力,这也是度量能力。这也是工具箱的一个整体规划。

最初版本的一个示意图,我们整个落地的形式是以IDE插件形式进行落地的。(本地IDE、云IDE版本)基本上包含了开发、测试、流程、客服、问题反馈这几个标签。

我们其实也引用了公司一些通用的工具以及一些开源工具。因为整体内容比较多,挑了两个可能对大家来说更通用一些的在环境、整个回归分析方面的方案进行一个更具体实例讲解。

本地环境直连集群

背景:微服务架构,k8s mesh 环境下。服务调用关系复杂,集成内外网络不互联,研发本地较难进行系统级自测,测试验证成本高

目的:修改代码后,快速进行端到端的验证。

基于这一块的问题,我们做了研发本地修改立马能得到系统级验证效果的一个整体方案,其实我们调研了,业界的一些主流方案,做了一个对比。

由于Telepresence需要在本地运行Docker,并且不支持多版本并存,最终采用了 kt-connect 作为底层方案。我们目前使用的方案的一个原理大概是这张图展示的一个样式。

分为正向通路、反向通路。

正向通路:本地服务如何访问集群里的另一个服务,目前是利用istio网关来做这个事情的。对外暴露地址,可以从本地开发机通过集群 istio 网关,在网关进行服务路由和转发。

反向通路:使用了kt-connect机制,集群服务A访问本地服务B,服务A访问集群内影子容器B,影子容器B部署一个ng 转发服务,当A访问本地B时,A转发至影子B的pod,再根据端口方向转发到本地真实地址上,从而从容器服务代理到本地服务。

这是我们目前正向通路、反向通路实现在的一个原理。

这是我们整体的在不同的场景之下,怎么样去实现本地跟集群环境的一个直接的互联互通

场景一 :紫色的这条线,开发机直接istio网关,然后通过网关直接走到ServiceB;

场景二:直接访问集群,集群的这一个请求能够访问到我的开发机。他走的其实就是橘色的这条线,我们的请求直接进去之后会直接到istio网关,网关他可能第一个访问的服务是ServiceA,ServiceA通过他的路由规则走到他的版本1或者是版本2 ,接下来调用ServiceB,实际上因为我需要调用到的是我本地的服务,所以实际上这里可以理解为 ServiceB的版本1,是我映射的一个容器,路由规则走到 ServiceB时,实际是走到了一个网终代理,网络代理会通过k8s端口映射,跳板机端口转发规则的一个读取,将搜索到的所有请求直接映射到我的本地服务里来。

场景三:本地浏览器和集群的互联,蓝色的这条线,浏览器直接缺访问的时候,和橘色的是一样的,整个通过里面容器的网络代理,去实现路由规则的一个转发

场景四:本地笔记本和集群的互联

我们这里有一个背景,部署机房和办公网络是单向连通的。办公网可以访问机房内的服务,机房不能访问办公网,这样就导致,研发使用本地办公网笔记本开发时,服务如果想要再调用本机服务的话,是无法再走到办公网的,所以利用了云 IDE插件的形式。

研发在本地笔记本开发,开发的 IDE 是使用云IDE,IDE代码部署在机房的远程机器上,在这台机器上进行联通。

这样办公网室使用云IDE的形式也可以使用整套转发流程,从而实现研发本地快速和远程集群进行联调。这个就是基于网络代理,多路复用的一个实践方案。

效果

在IDE插件中配置应用环境参数,插件会在远程集群生成影子pod,并自动生成转发规则,回调本地服务通知部署结果,以及服务调用标签。在测试环境,只要发送到集群的请求heads中带有这些标签,那么服务就会根据标签直接调用到本地实例上来。

这样研发在进行端到端验证时,就不需要再进行流水线部署,可以通过插件调用到整个服务集群中去,再通过标签识别的方式,精准的调用到自己的本地服务上。

修改后的验证成本从原来的10多分降低到2分钟左右,也抑制了未经验证的代码,提交导致的代码污染,还有一个好处是,转移了k8s测试集群资源压力到了普通开发机上,减少了测试环境资源占用。

改动影响面分析

影响面分析主要为解决,在复杂的微服务架构下,辅助研发进行代码影响范围分析,协助研发梳理自测重点。提高提测质量,减少测试人力投入成本。

后端服务

  • 静态调用关系采集:静态代码采集,采集调用链关系,做为静态图谱数据,目前是以图数据库方式进行存储,每个函数就是一个点。
  • 动态调用关系采集:利用Skywalking开源工具进行服务间调用关系采集,根据线上实时调用链关系进行采集和沉淀的。一般会使用近一个月的数据来生成动态调用链数据生成。

当有了静态和动态两部分调用链数据之外 ,会生成一个非常大型的线下调用关系图谱。包含了函数到服务、服务到服务之间整 个调用关系链。通过git diff获取代码diff内容,结合语法树分析获取到diff代码影响到的函数,然后再通过函数在静态图谱里做映射,就能知道修改的函数还影响了哪些对外出口的接口函数,以及通过这些接口再到动态调用链关系中查得到影响了哪些外部的接口。

通过三部分数据集合,可以算出一个网状图,修改了什么,影响到了什么,以及整个调用链接的一个关系。

前端服务

前端可能会稍微有点不一样,但大概的思路也是类似的。但是前端代码跟后端代码的差别是,后端代码是有比较明确的函数到接口,最终呈现的可能都是以一个接口或者所谓的 API 的形式去提供服务的。但前端可能不是,那我们怎么样去看前端的影响面,页面的范围可能太大了,所以我们可能需要对前端去做一些更细节化的拆分,能够让我们的这个影响面分析,最后产出的东西能够更具备可读性。

我们这边的话是去抽取的一个所谓组件的概念,这块和业务也是相关的,业务如果标准化做的比较好的话,公共组件的抽取会更加方便。但是如果标准化做的比较差的话,这一块可能会比较难做。在我们业务这边的话,基本上所有通用的一些控件,比如说查询框、穿梭图、表格等等的都是有标准的这种组件的,然后我们的每个页面,其实是由不同的这种组件来去拼凑而成的,而且组件本身是有互相引用的一个关系,那这一部分关系的话,我们可以根据业务代码的一些特征,需要跟前端同学去有一些沟通,去形成一个组件间的调用链关系的一个树,通过白盒的一个分析,AST语法树的一个解析,结合我们自定义的业务代码的特征的一些定义,然后组件和引用的一些关系的识别,通过这种方式来获取一个组件层面的类似于调用链关系的一个图谱。

然后我们存下来这个静态关系之后,就跟后端就是一样了,根据每一次 diff 代码的变更去看底层代码的改动,影响的上层给件到底是什么,组件与页面是什么样的关系,又会影响到哪些页面,从而去帮我们评估出来这一次改动,可能影响的页面是什么,以及影响到的这个页面里面可能我们需要重点关注的组件部分是什么。

然后通过这样的一个关系的话,我们就可以做一些前端层面影响面的一些分析,同时因为关联到的页面,我们还可以用线上的一些用户行为数据标注出来,本次影响的页面里面哪个是用户热度更高的页面,然后你应该更高优的去关注或者测试它,哪些是用户可能其实也不怎么用,如果真的测试排期特别紧张的话,那这些页面其实也可以放弃。

效果

基本上我们目前是以代码库和分支的一个方式,去查询出来,本次代码库本次分支,对应的一个影响面是什么。

变更影响分析结果:

  • 影响接口是什么;
  • 接口是因为哪一块代码变更影响;
  • 接口本身又影响哪些下游服务接口;
  • 变更内容、行数、逻辑改动、分类汇总等以及影响树等乖详情信息;
  • 大概变更风险图谱;
  • 接口被调用页面,调用关系图等等。

这就是我们目前整体的一个设计思路以及落地情况。


问答时间

1.像这种效能工具、云IDE插件,插件是谁研发的,这个效能团队的规模有多大呢

回答:插件是由QA团队做的。像百度QA白盒团队会提供的一些通用的基础能力。比如语法树分析、静态代码分析基础能力。业务的同学基于这些基础能力的基础之上结合业务自己的特征上,做一些适配,应用到工具层面上。

2.研发记录开发过程中耗时,是如何计算的?

回答:我们是偏半自动化的获取,所有的代码提交都是需要绑定需求卡片的,需求卡片上会有状态变更,每一步的状态变更都会有系统化的历时记录。

所以我们其实是采那个我们卡片上的状态变更的时间段,然后自动的去计算的,计算出,研发到底花了多长时间,测试到底花了多长时间,不过这个中间肯定是会有一些误差,但也不会太大。

3.就是那个我们 Local 这个工具箱,有智能客服的,他是怎么对所有的项目了解的呢?

回答:这个只是针对我们这个业务来进行的,比如说其他业务他想要做一个类似的版本,它其实代码框架是可以直接挪用过去,比如说白盒分析、测试分析这些东西。当然环境直连不行,因为各个架构不一样,但是你可以做类似的能力,但是客服可以绑定不同的账号的,不同的开发分支可以对应不同的业务线。

4.目前百度的开发测试比是多少?

回答:前后端不太一样,我们有的是端到端测试,有的是前端测试或者后端分开测试的,后端高的团队有 1:10 到 1:10 以上,低的估计都是 1:7 到 1:8。

前端的话会有一些外包测试,加上外包的话这个比例会低一些,端比较重的,可能是大概在 1:5。

5.做了这么多分析最终都是为了精准,这个影响面的这个准确度是有多高?

回答:白盒的这个数据只要采得准,他的推荐精准度是非常高的,但是其实可能会碰到的问题就是,一次代码改动之后,推荐出来的东西太多了,因为他会比人能看到的东西要多很多,所以这个问题就在于我们可能需要去区分他推荐出来的东西:

  • 哪些是更真实有用的?
  • 哪些是可能你不看也没有太大关系的?
  • 或者是说他推荐出来的其实可能会有很多重复的东西?比如说:同一个代码修改他影响了10个接口,你是不需要10个接口都测的,你可能测其中的一个就可以了,所以其实是要去找这样的一些关系的。

然后这块我们其实也有在看,比如他提供出了10个接口,那这10个接口里面哪个可能是用户用得更多的?哪个是原来以前出bug出得更多的?去采集对应的这一些数据来去作为同源的一个修改引起的这种推荐的话,我们可能最终给你浓缩成一个推荐,就是10个接口里面,我给你推最重要的这一个出来。

6.这个分析的工作是谁来做的,分析的工作量其实挺大的,是QA来做呢还是研发同学来做?

回答:这个是希望工具来做,这个特征也是可提取的,就可能你的初版本出来的时候是一大堆的影响面,这个我们是不可能给研发去看的,因为只会造成反作用,会说这个我没法看,所以最开始的时候肯定是做这个工具的人自己来看,从这个里面去发掘一些进一步的特征,比如说同源的一个识别、同源影响,是不是只应该推荐出其中的一部分。

另外,其实也可以去做一些反向的识别,就是比如说:很多个文件影响的是同一个接口,那这些文件的影响其实是应该被综合成一个问题来看。特征也是需要我们进里面再去多进一步挖掘的。

0 人点赞