流量录制回放工具jvm-sandbox-repeater入门篇——服务部署

趋于当前技术不断更新、产品功能多元化之下,流量回放的热度也是越来越高。

在前一段时间,测试团队也提到阿里开源的流量回放工具 jvm-sandbox-repeater

我个人就先尝试一下,期间还是遇到一些问题,通过咨询和度娘的帮助下,整体功能的使用流程是跑通了。

jvm-sandbox-repeater简介

在聊之前,我们先来了解下jvm-sandbox-repeater,其实在官网上也有详细的介绍,这里就直接搬官网的吧

jvm-sandbox-repeater是JVM-Sandbox生态体系下的重要模块,它具备了JVM-Sandbox的所有特点,插件式设计便于快速适配各种中间件,封装请求录制/回放基础协议,也提供了通用可扩展的各种丰富API。

目标人群

  • 线上有个用户请求一直不成功,我想在测试环境Debug一下,能帮我复现一下吗?

  • 压测流量不知道怎么构造,数据结构太复杂,压测模型也难以评估,有什么好的办法吗?

  • 不想写接口测试脚本了,我想做一个流量录制系统,把线上用户场景做业务回归,可能会接入很多服务系统,不想让每个系统都进行改造,有好的框架选择吗?

  • 我想做一个业务监控系统,对线上核心接口采样之后做一些业务校验,实时监控业务正确性。

如果你有以上的想法或需求,jvm-sandbox-repeater 都将是你的不二选择方案;框架基于JVM-Sandbox,拥有JVM-Sandbox的一切特性,同时封装了以下能力:

  • 录制/回放基础协议,可快速配置/编码实现一类中间件的录制/回放
  • 开放数据上报,对于录制结果可上报到自己的服务端,进行监控、回归、问题排查等上层平台搭建

repeater的核心能力

  • 通用录制/回放能力
    无侵入式录制HTTP/Java/Dubbo入参/返回值录制能力(业务系统无感知)
    基于TTL提供多线程子调用追踪,完整追踪一次请求的调用路径
    入口请求(HTTP/Dubbo/Java)流量回放、子调用(Java/Dubbo)返回值Mock能力

  • 快速可扩展API实现
    录制/回放插件式架构
    提供标准接口,可通过配置/简单编码实现一类通用插件

  • standalone工作模式
    无需依赖任何服务端/存储,可以单机工作,提供录制/回放能力

repeater的应用场景

  • 业务快速回归
    基于线上流量的录制/回放,无需人肉准备自动化测试脚本、准备测试数据

  • 线上问题排查
    录制回放提供"昨日重现"能力,还原线上真实场景到线下做问题排查和Debug
    动态方法入参/返回值录制,提供线上快速问题定位

  • 压测流量准备
    0成本录制HTTP/Dubbo等入口流量,作为压测流量模型进行压测

  • 实时业务监控
    动态业务监控,基于核心接口数据录制回流到平台,对接口返回数据正确性进行校验和监控

jvm-sandbox-repeater服务部署

环境准备

建议在Linux环境下使用,windows下可能会出现路径不一致的情况,我使用的环境如下:

  • Linux
  • JDK 1.8
  • Maven 3.2
  • Mysql 5.7

如果只是想简单体验下,则用不到Mysql,可以参考官网的用户手册

安装repeater

克隆源码

git clone https://github.com/alibaba/jvm-sandbox-repeater.git

安装repeater

进入到jvm-sandbox-repeater项目bin目录下,执行命令./install-repeater.sh

界面展示如下所示,则说明安装成功

修改repeater配置

路径为:~/.sandbox-module/cfg/repeater.properties

主要修改2个值

  • repeat.standalone.mode,修改为false
# 是否开启脱机工作模式
repeat.standalone.mode=false
  • url主机地址和端口,这个按需修改,每个人的服务器地址都不一样
# 录制消息投递地址
broadcaster.record.url=http://127.0.0.1:8001/facade/api/record/save

# 回放结果投递地址
broadcaster.repeat.url=http://127.0.0.1:8001/facade/api/repeat/save

# 回放消息取数据地址
repeat.record.url=http://127.0.0.1:8001/facade/api/record/%s/%s

# 配置文件拉取地址
repeat.config.url=http://127.0.0.1:8001/facade/api/config/%s/%s

说到这里,可能会疑问,为什么要修改这2个配置?原因如下:

repeat.standalone.mode控制 repeater 是否以 standalone 模式启动,我们要与 repeater-console 结合使用,所以配置为false

其他 url 都是与 repeater-console 交互的 url,所以需要将 host 改为本地启动的 repeater-console 的地址

修改console配置

console配置路径:/jvm-sandbox-repeater/repeater-console/repeater-console-start/src/main/resources/

# 使用本地数据源进行测试
console.use.localCache =false
# 示例回放地址(工程使用需要维护repeater插件的ip:port替换,指定ip发起回放)
repeat.repeat.url=http://%s:%s/sandbox/default/module/http/repeater/repeat
# 示例配置地址(工程使用需要维护repeater插件的ip:port替换,指定ip发起回放)
repeat.config.url=http://%s:%s/sandbox/default/module/http/repeater/pushConfig
# 示例重载地址(工程使用需要维护repeater插件的ip:port替换,指定ip发起回放)
repeat.reload.url=http://%s:%s/sandbox/default/module/http/repeater/reload

这里主要修改ip+端口,这个也是按实际服务配置来。console.use.localCache默认为false,不修改即可

建库建表

由于我这里是结合console一起使用,所以需要用到Mysql,自然就需要建立所需的数据库和表。建库建表语句在项目中是有的,路径为:/jvm-sandbox-repeater/repeater-console/repeater-console-dal/src/main/resources/database.sql,语句如下所示:

CREATE DATABASE IF NOT EXISTS repeater
    DEFAULT CHARSET utf8
    COLLATE utf8_general_ci;
DROP TABLE IF EXISTS repeater.record;
CREATE TABLE repeater.record
(
    id             BIGINT(20)    NOT NULL AUTO_INCREMENT PRIMARY KEY
        COMMENT '主键',
    gmt_create     DATETIME      NOT NULL
        COMMENT '创建时间',
    gmt_record     DATETIME      NOT NULL
        comment '录制时间',
    app_name       VARCHAR(255)  NOT NULL
        COMMENT '应用名',
    environment    VARCHAR(255)  NOT NULL
        COMMENT '环境信息',
    host           VARCHAR(36)   NOT NULL
        COMMENT '机器IP',
    trace_id       VARCHAR(32)   NOT NULL
        COMMENT '链路追踪ID',
    entrance_desc  VARCHAR(2000) NOT NULL
        COMMENT '链路追踪ID',
    wrapper_record LONGTEXT      NOT NULL
        COMMENT '记录序列化信息',
    request        LONGTEXT      NOT NULL
        COMMENT '请求参数JSON',
    response       LONGTEXT      NOT NULL
        COMMENT '返回值JSON'
)
    ENGINE = InnoDB
    COMMENT = '录制信息'
    DEFAULT CHARSET = utf8
    AUTO_INCREMENT = 1;

DROP TABLE IF EXISTS repeater.replay;
CREATE TABLE repeater.replay
(
    id              BIGINT(20)   NOT NULL AUTO_INCREMENT PRIMARY KEY
        COMMENT '主键',
    gmt_create      DATETIME     NOT NULL
        COMMENT '创建时间',
    gmt_modified    DATETIME     NOT NULL
        comment '修改时间',
    app_name        VARCHAR(255) NOT NULL
        COMMENT '应用名',
    environment     VARCHAR(255) NOT NULL
        COMMENT '环境信息',
    ip              VARCHAR(36)  NOT NULL
        COMMENT '机器IP',
    repeat_id       VARCHAR(32)  NOT NULL
        COMMENT '回放ID',
    status          TINYINT      NOT NULL
        COMMENT '回放状态',
    trace_id        VARCHAR(32)
        COMMENT '链路追踪ID',
    cost            BIGINT(20)
        COMMENT '回放耗时',
    diff_result     LONGTEXT
        COMMENT 'diff结果',
    response        LONGTEXT
        COMMENT '回放结果',
    mock_invocation LONGTEXT
        COMMENT 'mock过程',
    success         BIT
        COMMENT '是否回放成功',
    record_id       BIGINT(20)
        COMMENT '外键'

)
    ENGINE = InnoDB
    COMMENT = '回放信息'
    DEFAULT CHARSET = utf8
    AUTO_INCREMENT = 1;


DROP TABLE IF EXISTS repeater.module_info;
CREATE TABLE repeater.module_info
(
    id           BIGINT(20)   NOT NULL AUTO_INCREMENT PRIMARY KEY
        COMMENT '主键',
    gmt_create   DATETIME     NOT NULL
        COMMENT '创建时间',
    gmt_modified DATETIME     NOT NULL
        comment '修改时间',
    app_name     VARCHAR(255) NOT NULL
        COMMENT '应用名',
    environment  VARCHAR(255) NOT NULL
        COMMENT '环境信息',
    ip           VARCHAR(36)  NOT NULL
        COMMENT '机器IP',
    port         VARCHAR(12)  NOT NULL
        COMMENT '链路追踪ID',
    version      VARCHAR(128) NOT NULL
        COMMENT '模块版本号',
    status       VARCHAR(36)  NOT NULL
        COMMENT '模块状态'
)
    ENGINE = InnoDB
    COMMENT = '在线模块信息'
    DEFAULT CHARSET = utf8
    AUTO_INCREMENT = 1;


DROP TABLE IF EXISTS repeater.module_config;
CREATE TABLE repeater.module_config
(
    id           BIGINT(20)   NOT NULL AUTO_INCREMENT PRIMARY KEY
        COMMENT '主键',
    gmt_create   DATETIME     NOT NULL
        COMMENT '创建时间',
    gmt_modified DATETIME     NOT NULL
        comment '录制时间',
    app_name     VARCHAR(255) NOT NULL
        COMMENT '应用名',
    environment  VARCHAR(255) NOT NULL
        COMMENT '环境信息',
    config       LONGTEXT     NOT NULL
        COMMENT '配置信息'
)
    ENGINE = InnoDB
    COMMENT = '模块配置信息'
    DEFAULT CHARSET = utf8
    AUTO_INCREMENT = 1;

执行完建库建表语句后,就会生成对应的四张表了。

修改repeater项目代码

  • #parse("/blocks替换为#parse("blocks

路径为:/jvm-sandbox-repeater/repeater-console/repeater-console-start/src/main/resources/velocity,将velocity路径下的所有文件,存在#parse("/blocks的替换为#parse("blocks

这个点,我是看之前的文章有提及,但我拉取源码来看的时候,这个点的问题已经不存在的,源码中就已经是#parse("blocks

所以我这个点没有修改代码

  • 修改 ReplayController.java

路径为:/jvm-sandbox-repeater/repeater-console/repeater-console-start/src/main/java/com/alibaba/repeater/console/start/controller/page/ReplayController.java,将return "/replay/detail";修改为return "replay/detail";,去掉双引号里面第一个 /

  • 修改 RegressPageController.java

路径为:/jvm-sandbox-repeater/repeater-console/repeater-console-start/src/main/java/com/alibaba/repeater/console/start/controller/test/RegressPageController.java,将return "/regress/index";修改为return "regress/index";,去掉双引号里面第一个 /

启动repeater项目

进入到路径:/jvm-sandbox-repeater下,使用命令mvn clean install -Dmaven.test.skip=true && java -jar repeater-console/repeater-console-start/target/repeater-console.jar,出现如下所示内容,说明项目构建成功

出现如下所示内容,说明repeater项目启动成功

访问repeater-console页面

通过url http://ip:端口/regress/index.htm,访问页面,进入到如下测试页面,说明通过url访问也ok,服务没有问题

该页面总共三个菜单:在线流量、配置管理、在线模块

先简单讲下,在线流量就是录制的请求,配置管理就是针对要录制的应用配置,在线模块就是sandbox的心跳。后续文章会继续讲到,今天先简单描述下。

问题

./install-repeater.sh执行失败

执行命令,出现如下报错

解决办法:

通过命令 vim install-repeater.sh 将 tar xz 中的 z 删除即可,因为该压缩包没有用gzip格式压缩,所以不用加z参数

启动repeater项目空指针

启动repeater项目提示空指针,报错如下所示:

解决办法:

module_config、module_info表中的appname和environment不一致,修改为一致即可

以上就是今天分享的内容,下期再会。

posted @ 2022-05-05 09:01  温一壶清酒  阅读(5420)  评论(0编辑  收藏  举报