导读:百度测试中间件是百度 QA 自主研发的底层根底技术,历经 10 年的一直倒退,采纳数据立体 + 管制立体的总体架构,与 google istio 设计理念殊途同归,反对 8 大性能,9 大测试场景,笼罩百度团体各大产品线,目前接管拓扑 1w+,接管链路 1w+,利用中间件技术,能够大幅晋升联调环境搭建效率、模块免测率,大幅晋升环境仿真度,线上环境安全性,是测试中必不可少的外围工具。
引言
本文提出一种基于中间件技术的测试计划,并介绍该办法在百度各类测试场景中的利用实际。
一、百度测试中间件是什么
百度测试中间件 (以下简称中间件) 是百度 QA 自主研发的中间件,历经 10 年的技术倒退,目前曾经成为百度各条产品线测试中必不可少的基础设施。它是一种网络代理,接管模块之间的通信链路后,在数据层面能够解析、批改数据包,在行为管制方面,能够管制申请和返回数据的路由行为,能够退出熔断、过滤、限速等机制,从而满足各类测试场景的需要。
纵观业界,各类网络代理多种多样,其中技术影响力最大的是 google 的 istio,简略来讲,istio 零碎由两局部组成:
1、数据立体
数据立体指的是网络代理这层,底层采纳 envoy 作为代理,以 sidecar 的模式与用户服务同机部署,服务与服务之间不再间接通信,而是先和本机的 envoy 先通信,envoy 与 envoy 进行通信,envoy 能够对通信数据做数据层面或者行为方面的管制。
2、管制立体
管制立体就像是大脑,能够给数据立体下发控制策略,数据立体充当执行者的角色,执行管制立体下发的控制策略,同时管制立体还能够收集数据立体的状态,从而理解整个零碎的状态。
能够看到,istio 采纳数据平台 + 管制立体的设计思维,能够有机的管制整个零碎,那么是否能够将此设计思维利用到测试畛域呢?答案是必定的,百度外部在 2010 年左右就有相似的网络代理,在 2016 年给网络代理加上了管制立体,2017 年在公司内公布,在各条产品线一直利用落地,整体思维与 istio 殊途同归,公布工夫也是不分前后。不同的是,istio 更多的是从开发或者运维角度来治理整个零碎,而中间件更加侧重于测试场景所需的各种能力,例如录制、回放、路由、改包等能力,并补充测试场景所必须的组件,提供整套开放式 API,不便与各类环境搭建工具或测试驱动程序相结合,从而满足各类测试场景。
二、测试环境的挑战
让咱们把眼光转移到日常的测试工作中,在测试的各个阶段都须要搭建测试环境,尤其是联调测试,更须要疾速搭建一套高度仿真的测试零碎。这里以被测版本 B1 须要联调测试为例,从历史教训来看,咱们大略经验了以下三个阶段来满足此类性能联调需要:
- 齐全搭建一套联调环境:整个拓扑须要搭建 7 个模块,如果每个模块联调都须要搭建这样一整套环境,很节约机器资源,并且环境筹备工夫很长,显然不是一种好的解决方案。
- 保护一套基准版本的全零碎:首先搭建一套残缺的基线版本的测试零碎,而后将测试版本的 B1 部署至基线环境,这种计划会导致整个零碎的稳定性会变差,在多个我的项目并发的状况下,稳定性问题会成倍扩充,仿真度也不满足需要。
- 保护一套基准版本的全零碎,进行分时复用:与下面计划二大致相同,不同的是,不同模块在应用环境时须要排队进行分时复用,稳定性尽管有所晋升,但测试效率非常低。
除了环境仿真度和测试效率方面带来的挑战,随着越来越多的模块微服务化,模块数量暴增,服务间依赖的等级也不尽相同,如何组建一套测试环境来测试零碎的整体稳定性又是另外一个层面的挑战。
咱们能够把下面的问题进行进一步的形象,在联调测试中,咱们面临的是测试资源和测试效率方面的问题,咱们是否能够复用一套测试资源,将测试流量进行隔离呢?这里须要的就是中间件的路由能力,在测试零碎整体稳定性时,咱们须要一种灵便的模仿机制,在通信链路层面模仿各类网络异样,这里须要的就是中间件的链路控制能力,所以咱们把各类测试场景形象后,都能够归结为某种链路数据或链路行为层面的问题,而这正是中间件所善于的,在上面的章节中会具体介绍中间件零碎的设计思路。
三、设计思路
1、零碎组成
- 申请平台:整个零碎是以服务化的模式对外提供服务,以平台或者 API 的模式与用户或其余零碎进行交互,申请平台的作用就是将用户的需要转化为配置核心能够辨认的配置。
- 配置核心:即管制立体,是整个中间件零碎的大脑,接管申请平台发过来的配置,以结构化的配置进行存储。配置核心以 zookeeper 为底层,对整个被测系统进行了 3 个档次的形象:
1)链路信息:对每个产品线的不同链路的通信协定进行形容,包含申请和返回方向的包头、包体格局等信息,通过这些配置,中间件代理能够解析通信链路中的数据,为进一步在数据和行为方面的管制打下基础。
2)拓扑信息:环境搭建工具会将整个拓扑中各个模块的部署信息通过 API 传递给中间件零碎,这样中间件零碎就能够晓得各个模块的部署地址,从而实现通信数据的整个转发过程。
3)策略信息:策略信息就是管制立体心愿数据立体须要做的具体事件,此项配置来源于申请平台,例如用户能够在申请平台抉择须要管制的链路,并指定该链路的行为,例如路由、录制、改包等,申请平台会主动将用户需要转化为中间件代理能够辨认的配置信息,中间件代理对此配置实时热加载并即时失效。
除此之外,中间件代理还会将所代理链路的地址(中间件链路地址)主动汇报给配置核心的 NB_CLUSTER 节点,上游模块连贯到此地址,实现对中间件代理的服务发现过程。
- 中间件代理:是整个零碎的执行者,能够实时 watch 配置核心的配置变动,热加载实时失效,采纳 c ++ 语言编写,性能十分高,中间件代理通过接管零碎中的局部或全副链路,与测试环境组成满足特定需要的测试环境。
- 数据中心:因为测试场景的需要,中间件零碎接管通信链路之后,须要录制申请和返回方向的数据,前面能够利用中间件代理 + 录制数据实现对实在后端模块的模仿,即 mock 后端模块,中间件所录制的数据就存储在数据中心中。
- 日志核心:因为中间件代理能够是个近程的集群,集群中的有多个同质化的实例,也能够以 sidecar 的模式部署在被测模块所在的机器上,如果日志只在本地存储,后续定位问题时将会十分的繁琐,所以须要一个集中式的日志核心将所有日志进行存储,并提供日志查问服务。
- 控制中心:控制中心与配置核心的作用相似,都是向中间件代理下发管制命令,不同的是,配置核心是面向全局的管制,即所有的中间件代理都能够从配置核心加载雷同的配置,并且这类控制策略都是由用户提交的测试需要,而控制中心能够独自给某个中间件代理发送管制命令,是一种部分管制,这类控制策略少数是由中间件开发者或维护者收回,少数用于运维或治理需要,例如在定位问题时,须要独自关上某个代理的 debug 日志,能够通过控制中心进行独自管制。
2、工作模式
整体来讲,中间件代理分为两大工作模式,即集群模式和本地模式,两种模式各有千秋,可能满足不同的测试场景。
- 集群模式:中间件代理以近程集群的形式提供服务,集群中部署多个同质化的实例,在这种模式下,中间件代理能够动静开启和开释链路,用户的每个申请对应于一条链路的开启,每个申请的开释对应于一条链路的开释,整个中间件集群反对 2 万条链路同时工作,能够了解为整个中间件集群是一个十分弱小的代理中心,因为被测模块与中间件集群是近程通信,所以不可避免的会带来通信延时方面的开销,所以此模式实用于对通信时延不敏感的测试场景,例如 diff、stable 测试、功能测试或性能联调测试等。
- 本地模式:顾名思义,是将中间件代理与被测模块以 sidecar 的模式进行同机部署,因为是同机部署,被测模块和中间件代理之间简直没有通信提早,此模式实用于对通信延时敏感的测试场景,例如性能测试场景,对后端的性能稳定要求十分高,还有混沌场景,因为自身就是要在通信过程中注入延时,如果应用集群模式还会带来额定的通信延时,造成试验成果不精确,除此之外,因为混沌场景大多采纳线上实在环境进行试验,整体流量十分大,如果采纳集群模式,会须要十分多的资源能力搭建进去并满足测试需要。
3、整体工作流程
- Step1 申请服务:用户通过申请平台或者 API 描述测试需要,实质上来讲,就是通知中间件零碎心愿在哪条链路执行什么样的操作,例如在 A2B 链路执行路由操作,路由到 B1
- Step2 生成链路:申请平台将用户需要转换为策略配置,存储在配置核心中,中间件代理通过 watch 机制,实时加载策略需要,并实时生成对应的中间件链路,例如图中的 A2B 和 B2C 链路。
- Step3 链路接管:中间件链路生成后,会将中间件链路地址汇报给配置核心,环境搭建工具在搭建上游模块时,会通过中间件的服务发现 API 失去中间件 A2B、B2C 链路的地址,并将 A、B 模块的上游连贯到中间件,此外环境搭建工具还会将整个拓扑的部署信息以 API 的模式传递给中间件,所以中间件各个链路能够实现对上游模块的服务发现,即 A2B 链路的中间件连贯到模块 B,B2C 链路的中间件连贯到模块 C,这样中间件就实现了对 A2B 和 B2C 链路的接管。
- Step4 策略失效:用户通过给整个环境的入口模块 A 发送申请后,此申请会流经中间件的各条链路,中间件会判断以后链路是不是用户指定的链路,如果不是,则间接转发给拓扑节点中配置的上游,如果是,则执行用户指定的策略需要,例如 A2B 链路,中间件就会将申请转发给 B1,B1 的上游连贯 B2C 链路的中间件地址,这样这个申请就绕过了基线版本的 B,整个申请的转发门路为 AàB1àC, 此外用户还能够在其余链路指定不同的测试需要,例如录制需要,中间件就会在指定链路将申请和返回的数据保留到数据中心。集群模式与本地模式的中间件工作机制是相似的,不同的是,集群模式的中间件是面向所有用户的,每个用户的需要对应其中的一条链路,本地模式的中间件只会服务于某个特定用户,所以稳定性和转发效率更高。
四、利用场景
中间件在百度外部的测试场景利用十分宽泛,从线下测试到线上测试场景都有所利用,例如在功能测试阶段,利用中间件的改包能力,能够模仿各种返回数据,通过联调平台,用户能够在一套基线环境内,利用中间件的路由机制,组成多路复用联调环境,满足多个测试项目同时联调,在线上环境中,用户通过中间件精准的网络异样注入,能够实现申请级别的混沌场景,上面会一一进行具体解说。
1、功能测试
功能测试在 APP 端测试中利用十分宽泛,中间件会生成一个链路,接管端和服务端之间的链路,具体工作流程如下:
- 创立空链路:中间件为每个产品线创立一条没有任何策略的数据通路,即 mock 代理
- 创立 mock 策略:在 mock 代理中创立 mock 策略,包含端辨认策略,服务端辨认测试和改包策略,中间件依据端辨认策略和服务端辨认策略动静辨认申请并执行对应的改包策略,同一产品线的多个用户能够共用一个对立的 mock 代理从业务需要角度来讲,在测试端性能的时候,对服务端的返回数据须要进行稳固的数据 MOCK 和异样的数据 MOCK。
- 稳固的数据 MOCK:这种模式是为了满足端上特定的性能场景,例如模仿固定的模板数据,回归不同模板数据在端上的成果。
- 异样数据 MOCK:这种模式是是为了测试端上加载异样数据时的体现,例如测试 APP 端在加载异样数据的状况下是否 crash。
从中间件的角度,改包策略有四种,AUTO,DATAID,CALL_BACK 和 USER_DEFINE 模式,别离满足不同的测试场景。
- AUTO:主动批改模式,中间件内置了 29 种主动批改数据策略,例如依据不同数据类型主动模仿边界值,跨类型批改等。
- DATAID:数据替换模式,能够对返回数据进行全副或局部替换。
- CALL_BACK:容许用户以 API 的形式提供数据,中间件通过调用 API 获取用户数据,而后进行 MOCK。
- USER_DEFINE:这种形式容许用户对服务端返回的实在数据实时进行批改,用户能够指定数据中的某个 key,并批改为用户指定的 value,用于满足特定的测试场景。
2、零碎级测试
零碎级测试场景指的是单模块的 diff、stable 测试场景,此场景须要保障基线版本和测试版本的模块具备雷同的输出和后端返回,测试被测模块的返回是否有 diff,具体工作流程如下:
- 接管链路:搭建录制子环境,中间件接管录制链路
- 发压录制:压力云给录制子环境发压,即可进行录制
- 保留数据:录制完结后,A2B 数据保留至申请数据管理平台,C2B,D2B,E2B 数据保留至数据中心
- 后端 mock:搭建回放子系统,被测模块 B 和 B’,别离连贯中间件回放链路,中间件从数据中心中读取数据并返回,实现后端 mock
这里要特地阐明的就是数据中心存储数据的形式,数据中心底层采纳的是 redis,是一种典型的 key-value 存储,所以对数据 key 的设计尤为重要,这里采纳的是工作标识 + 链路标识 + 申请标识三种因子联结计算 sign,造成 key,工作标识能够辨别不同申请工作的数据不互相笼罩,链路标识能够辨别同一个申请不同链路的数据不互相笼罩,申请标识能够将同一个工作,同一个链路中的不同申请进行辨别。value 是返回方向的数据,这样在数据录制阶段就造成了申请和返回数据之间的对应关系,所以在回放子环境中,同样的申请发来的时候,中间件通过计算会失去雷同的 key,而后失去对应的 value,并将此数据返回给上游模块,这样就对实在后端进行了 mock,从而被测模块 B’的后端都会有稳固的一致性返回,可能更精准的测试出基线版本的 B 模块和测试版本的 B’模块本身的 diff。
3、联调测试
在文章结尾,咱们提到了联调测试面对的痛点问题,在这里咱们利用中间件的申请级路由能力,复用一套基准环境,具体工作流程如下:
- 链路接管:保护一套基准环境,中间件接管各条链路
- 染色标记:发压工具对申请进行标记
- 路由:中间件依据申请标记,在指定链路路由到指定上游
- 被测模块与基准环境组成了一套残缺的联调环境
这里要特地阐明的是,这种联调模式是对原有联调环境的微小颠覆,将多路复用思维体现的酣畅淋漓,对测试效率的晋升是微小的,对测试资源的节俭也是微小的,用户还能够对此环境进行极致的多路复用,即不单单是在不同链路进行路由性能,还能够在不同链路进行数据录制或者改包,这样就能够把这套环境打造为一套真正的多路复用零碎。
4、沙盒测试
沙盒零碎是在线下搭建的一套仿真测试零碎,在流量仿真、环境仿真和环境搭建效率方面都有很高的要求。
- 流量仿真:传统形式是采纳线上引流形式,将线上流量实时复制到线下沙盒环境,但这是一种“靠天吃饭”的形式,流量仿真的必然性十分大,在测试零碎中,往往须要补充非凡的测试流量,以满足特定的测试场景,所以此时能够引入中间件,抽取肯定比例的线上流量,并实时批改为特定申请的款式转发给沙盒零碎。
- 环境仿真 & 环境搭建效率:沙盒零碎尽管是一套仿真零碎,但在资源无限的状况下,只能在肯定水平内进行环境仿真,在前端模块测试时,心愿后端环境是仿真的,所以能够利用中间件的动静路由机制 + 安全策略拜访线上后端环境,在后端模块测试时,同样能够利用路由机制,复用沙盒环境中的前端模块,因为被测模块并没有真正部署到沙盒基线环境中,所以并不会对整个沙盒零碎带来稳定性方面的问题,在多个我的项目同时进行测试时,环境的复用度会进一步晋升,从而能够进一步晋升环境搭建效率。
下面提到的中间件安全策略有 3 种,即熔断、过滤和限速策略。这三种策略是基于线上问题的形象。
- 熔断:中间件在转发线下申请的时候,首先会调用线上后端稳定性 API,当线上环境产生异样时,中间件会即时熔断,当线上环境复原时,中间件会主动复原对线上环境的拜访。
- 过滤:线下测试申请可能会对线上环境造成毁坏,例如线下环境不小心关上了降级开关,降级流量如果间接发给线上环境,会间接造成线上环境降级,中间件会对降级和低质流量进行辨认并间接过滤。
- 限速:线上环境调配给线下测试的容量是固定的,所以中间件须要做整体限速,能够做到对数据包的限速或者对某种申请标识进行限速,从而对线上环境进行爱护。
5、混沌工程
混沌工程是中间件以 sidecar 的模式部署到被测模块所在机器,并反对部署在 client 端或 server 端,例如如果须要模仿第三方依赖的异样,因为是第三方依赖,中间件往往不不便部署在第三方依赖的服务上,所以能够部署在 client 端,如果是大扇出模块,每条扇出链路都会有很多的实例,在混沌测试时须要充沛模仿被测模块对后端的调度机制,所以能够将中间件部署在 server 端,在调度仿真度上做到 100% 仿真。中间件能够反对对交互数据的异样和交互行为的异样,并可能深刻业务场景,精细化的模仿网络交互异样,例如模仿模块建设连贯之后的断开,这是其余工具无奈做到的,配合染色机制,中间件能够做到精准异样注入,做到 query 级别的异样注入。
工作流程如下:
- 染色标记:将实在流量进行染色
- 异样注入:中间件只对染色流量进行异样注入,非染色流量间接转发上游
- 中间件对染色流量进行申请级准确异样管制,准确管制爆炸半径,失常流量不受损失
五、技术生态
中间件零碎通过多年的落地打磨,目前曾经服务于百度外部各大产品线,落地 9 大测试场景,通过对 9 大测试场景的形象,将不同测试场景形象为 8 大原子根底测试能力,通过不同原子根底能力的不同组合,满足不同的测试场景,一方面,中间件零碎采纳同一套基础架构 + 8 种根底能力一直辅助业务倒退,另一方面,通过一直的业务落地反哺技术的晋升,造成双向无益的技术生态。
六、技术实质
中间件从最开始的简略的网络代理一直倒退,联合管制面弱小的控制能力,通过对通信数据和通信行为方面的管制,逐渐过渡到对整个零碎的管制,中间件曾经是测试环境的一部分,与被测模块独特组成用户所需的特定用处的测试环境。
作者:百度架构师
原文链接:https://mp.weixin.qq.com/s/rjToB9qxv47rUrwcBhzpjA
百度架构师
百度官网技术公众号上线啦!
技术干货 · 行业资讯 · 线上沙龙 · 行业大会
招聘信息 · 内推信息 · 技术书籍 · 百度周边
欢送各位同学关注!