27

流量回放框架jvm-sandbox-repeater实践二

 3 years ago
source link: https://tech.kujiale.com/liu-liang-hui-fang-kuang-jia-jvm-sandbox-repeaterde-shi-jian-2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前文链接: https://tech.kujiale.com/liu-liang-hui-fang-kuang-jia-jvm-sandbox-repeaterde-shi-jian/

1.前言

前文中,我们已经介绍了jvm-sandbox-repeater的原理,以及我们对它的初步实践。本文将进一步介绍我们目前的平台化实践工作。我们将该平台称为kurepeater。篇幅限制,这里主要介绍下kurepeater的基本架构和录制回放的优化设计。

2.基本架构

kurepeater主要由repeater(jvm-sandbox-repeater)、console、es、db、前台页面5部分组成。前端页面结构参考了官方demon并结合实际需要进行设计,采用公司内部框架进行开发;后台基于官方开源代码,并进行一些定制化的改造。

前台页面只和console进行交互,console操控整个流程。各模块间交互关系如下图所示。

N3uQvuQ.png!mobile

要启动repeater进行录制时,需先从前台进行配置和模块安装。配置我们存储在了DB里面。模块安装负责将jvm-sandbox-repeater安装到目标服务器上。点击激活,启动和录制流程如下图。录制数据序列化后存入es

UvY7ZvU.png!mobile

录制结束,可以在前台选择需要回放的流量和方式,通知console。后台回放流程如下。

rmYvYbR.png!mobile

回放成功后,我们可以在前台页面查看回放结果数据,成功失败信息,并对失败接口进行排查。

3.录制优化

平台化后,使用kurepater平台对流量进行录制,特别是线上环境,遇到了如下两个问题

1)有些接口不想录制怎么办

2)线上各接口流量严重不均衡,高频接口录制了一堆,低频接口可能一次都没录到

对于问题1,一开始我们在白名单httpEntrancePatterns里面写正则过滤这些接口,比如^((?!/error)).*然后重新启动服务。但是频繁的修改httpEntrancePatterns和重启服务比较麻烦,另外正则配置在辨识度和易用性上也存在一定的困难。为此,我们增加了黑名单blackEntrancePatterns过滤功能。与httpEntrancePatterns相对应,在blackEntrancePatterns中的接口都不录制。blackEntrancePatterns优先级高于httpEntrancePatterns。

对于问题2,其中一种解决办法就是当某个接口录制的量太大了,我们就把这个接口加进黑名单,然后重新激活服务继续录制。如此循环,确保高频接口量不至于太多,低频接口也有录制到。当要录制的接口比较少时,这种方法还行。但当要录制大量接口时,这种操作就有点繁琐尴尬了,所以最好是一开始就根据不同的接口qps赋予接口级别采样率。

为此,我们在官方实现的http插件里面加了点代码,大致如下

ZR7ruuN.png!mobile

前端配置界面如下。第一个采样率是统一的采样率,供所有需要录制但是没有特别强调接口采样率的接口使用。console里面的配置读存也做了修改。

aiEn2aE.png!mobile

4.回放优化

录制流量后对流量进行回放,发现回放结果比对失败的很多。经过对失败原因进行排查和统计,发现有些是真的新代码有bug导致的失败,但更多的失败并不是代码bug,例如

1)代码修改,修改了子调用,导致mock失败

2)有不支持的子调用,导致失败

3)子调用有随机参数相关,导致mock匹配不上

4)响应的内容用了随机数或者时间相关参数,导致比对失败

7)repeater代码缺陷

还有一些其它原因,这里不一一赘述。失败原因很多,真正有效的失败数很少。如此一来,每次回放失败的排查成本就非常高,这违背了我们的初衷,也给平台的内部推广带来了困难。我们迫切期望过滤无效的失败,节约不必要的排查时间。

4.1 diffy降噪

为了提高回放结果失败的有效性,我们先尝试了过滤字段功能,diff校验时对某些字段不进行校验。

3EvYNzJ.png!mobile

这种方案对单接口回放测试时比较有效。但是他只针对上述常见失败原因的第4条。而且如果想批量回归某个服务的所有接口,加之服务接口增加和迭代,使用起来就会比较麻烦。我们还是需要一种可以智能降噪的方式。为此我们使用了diffy工具来进行降噪。

diffy能够通过比较candidate(候选版本)和primary(稳定版本)和secondary(稳定版本副本)的差异值来消除噪声,得到最终的diff结果。原理如下图,具体介绍网上很多,这里不仔细介绍。

NvMrMbj.png!mobile

我们在diffy开源代码的基础上做了修改,提供了如下接口功能。如下图,此时left传的是回放目标服务的响应,right传的是录制服务的响应,right2传的是降噪服务的响应。

AzauMn6.png!mobile

可以看到,接口请求diffy告诉我们BCD三个字段的响应值不同。其中C和D字段noise为1,表示在降噪环境回放也是不对的,不具备比较和排查意义,只有B这个字段需要排查。

所以假如我们在线上环境(prod)进行了流量录制,欲要回放到开发环境(dev),不妨使用一个线下稳定环境(stable)进行降噪。将三个环境的响应值都调用diffy进行比对,如果最终diff结果都没有差异,或者有差异的字段noise都为1,就可以认为这条回放是成功的。

4.2 流量过滤

进一步考虑,既然我们需要回放到stable环境和dev环境,那么我们可以在回放到stable的时候对流量就先进行一个过滤,对那些明确会回放失败的流量我们就没必要再回放到dev了,比如有暂不支持的插件。这里需要判断怎样的流量是没有必要回放的,即无效流量。简单逻辑如下

6B7jAbE.png!mobile

stable回放结果diff我们这里依旧使用了官方的,字段过滤逻辑保留。如果回放diff失败了,且有子调用mock没有兜住。那么说明他的代码走了新的链路,或者子调用请求中有较多随机数等。此时这些流量回放到dev去也难逃失败的命运,所以可以过滤掉这部分流量。反之,则可将流量回放到dev去。

4.3 回放流程逻辑

基于以上diffy降噪和流量过滤,降噪回放整体流程设计如下图所示

RNRVjiE.png!mobile

前端入口设计如下

mqm6ne2.png!mobile

kurepeater支持在前端选择是否降噪。选择降噪则进行流量过滤和diffy比较;选择不降噪则走原逻辑,直接回放到目标服务,使用开源代码自带的diff工具进行比较。

4.4 效果数据

下面是我们某一次回放的实验结果。如果我们选择不降噪,那么共回放了38500条,回放失败249条。这样回放排查的工作量是很大的。

MziyAjN.png!mobile

选择使用降噪功能后,经过滤能走到dev流量只剩约19870条,失败只剩约120条,都少了约一半。排查的工作量依旧是很大的

NFVV3mq.png!mobile

降噪回放查看结果时把diffy降噪判断的打开进行过滤,此时需要我们去仔细排查确认的只剩两条,如此就比较轻松了

EJFJnav.png!mobile

5.总结:

kurepater平台已经在公司内部开始推广试用,目前已共在几十个服务上进行了数千次回放,回放功能对部分服务代码的行覆盖率已达到了40%以上。下一步,我们将考虑提升kurepeater平台的易用性,比如增加更多的插件支持,进一步优化接口采样配置,优化问题的排查效率等。感兴趣的可以一起讨论和学习。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK