开源测试工具 [jvm-sandbox-repeater 学习笔记][原理说明篇] 1 录制流程

ELes for PPmoney · 2019年10月22日 · 最后由 白云黑狗 回复于 2022年08月08日 · 15867 次阅读
本帖已被设为精华帖!

repeater 系列学习笔记进入第二部分,原理说明篇。

本篇章会结合录制回放的流程进行源码的导读,并且附上我的学习解析,可能有讲得不对、不够好的地方,欢迎大家留言指正~

jvm-sandbox-repeater 学习笔记系列的文章建议按照顺序阅读~附上前序篇章:入门使用篇的传送门

1.1 录制流程图

如下图,描述了用户触发请求,当 sandbox 感知到调用事件到录制结果保存的过程。

录制流程图

1.2 录制过程步骤的源码解析

在整个录制过程中,repeater 进行录制的处理流程是DefaultEventListener类中实现。

接下来我们将以这个类作为入口去了解录制过程的处理逻辑。

1.2.1 DefaultEventListener 类

DefaultEventListener实现了 sandbox 的 EventListener 接口,是用来处理触发事件的类。

在 repeater 中,不同的插件可以自定义自己的 EventListener 来进行各自特殊的事件处理。而在当前的代码中,除了 http 插件,其他插件都使用的是默认的DefaultEventListener

DefaultEventListener中,承接的是所有事件的处理,也就是说无论是录制操作,还是回放操作,都是集中在这个类中实现的,只是根据不同的条件来区分是录制流量还是回放流量,从而判断该执行录制还是该执行回放。

在上面的流程图中,repeater 中的流程执行,实际上是DefaultEventListeneronEvent的流程图。接下来我们一个一个流程去解析录制过程的实现。

1.2.2 事件过滤

在整个事件处理过程中,总共经历了两个阶段,四个事件过滤。

过滤顺序 过滤说明 实现方法
1 针对单个 listener,只处理 top 的事件
不同的插件之间的 listener 相互隔离,所以即使是录制 http 的请求,java 子调用插件的事件也能通过过滤。
DefaultEventListener.isTopEvent
2 进行基础过滤,主要根据系统熔断、降级进行判断。该过滤条件与 repeaterConfig 中的 degrade 字段、exceptionThreshold 字段有关。 DefaultEventListener.access
3 执行采样计算(只有 entrance 插件负责计算采样,子调用插件不计算),该过滤条件与 repeaterConfig 中的 sample 字段有关。 DefaultEventListener.sample
4 判断是否是插件调用处理器设置为忽略的事件。每个插件处理不同。 processor != null && processor.ignoreEvent((InvokeEvent)event)

1.2.3 初始化跟踪器

当事件通过第一个过滤时,就会进行跟踪器初始化。

/**
     * 初始化上下文;
     * 只有entrance插件负责初始化和清理上下文
     * 子调用无需关心traceContext信息(多线程情况下由ttl负责copy和restore,单线程由entrance负责管理)
     *
     * @param event 事件
     */
    protected void initContext(Event event) {
        if (entrance && isEntranceBegin(event)) {
            Tracer.start();
        }
    }

跟踪器相关的内容在 com.alibaba.jvm.sandbox.repeater.plugin.core.trace 包中。

其中我们提到的 traceId 实际上是这个跟踪器的独立标识。所以无论是录制和回放都会有其独立的 traceId。

1.2.4 Before 事件处理

对应的方法是DefaultEventListener.doBefore

  1. 判断当前流量是否为回放流量,若为回放流量则调用processor.doMock方法执行 Mock,不执行后续操作。

  2. 若当前流量非回放流量,则基于当前获取到的信息拼接Invocation实例。其中会调用插件调用处理器的 assembleRequest、assembleResponse、assembleThrowable、assembleIdentity 方法进行请求参数、返回结果、抛出异常、调用标识的拼接。

  3. 根据插件调用处理器的设定,判断是否需要进行Invocation中的 request、response、throwable 参数的序列化。

  4. 将当前事件的 Invocation 信息存放到录制缓存中。

1.2.5 Return 事件处理/ Throw 事件处理

return 事件与 throw 事件的处理逻辑基本一致。

  1. 判断当前流量是否为回放流量,若为回放流量则不执行后续操作。

  2. 从录制缓存中获取对应的Invocation实例,如果获取失败则打印失败日志,不执行后续操作

  3. Invocation实例获取成功后,调用插件调用处理器的 assembleResponse 或者 assembleThrowable 方法将 reponse 或者 throwable 信息设置到Invocation实例中。并设定Invocation的结束时间。

  4. 回调调用监听器InvocationListeneronInvocation方法,判断 Invocation 是否是一个入口调用,如果是则调用消息投递器的 broadcastRecord 将录制记录序列化后上传给 repeater-console。如果不是则当做子调用保存到录制缓存中。

PS:消息投递器当前支持两种模式,在 standalone 模式下,保存到本地文件;在非 standalone 模式下上传到 repeater-console。

共收到 6 条回复 时间 点赞
陈恒捷 将本帖设为了精华贴 10月26日 18:23

楼主有心了

ELes #6 · 2019年12月09日 Author
81—1 回复

能帮上忙就好啦~大家多交流~

simple [精彩盘点] TesterHome 社区 2019 年 度精华帖 中提及了此贴 12月24日 23:00
simple [精彩盘点] TesterHome 社区 2019 年 度精华帖 中提及了此贴 12月24日 23:00
江蓠 流量回放框架 jvm-sandbox-repeater 的实践 中提及了此贴 05月11日 02:56
仅楼主可见
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册