jvm-sandbox-repeater 精简版部署之standalone模式

2023-12-15 01:15

本文主要是介绍jvm-sandbox-repeater 精简版部署之standalone模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

jvm-sandbox-repeater 仅仅提供了录制回放的能力,如果需要完成业务回归实时监控压测等平台,后面须要有一个数据中心负责采集数据的加工、存储、搜索,repeater-console提供了简单的demo示例;一个模块管理平台负责管理JVM-Sandbox各模块生命周期;一个配置管理平台负责维护和推送jvm-sandbox-repeater采集所须要的各种配置变更

在阿里集团淘系技术质量内部,已有一套完整的体系在持续运行,从17年开始支持了淘系技术质量部的CI、建站、系统重构等多方面质量保障任务,后续如有需要也会考虑把更多的东西开源回馈社区

注意:目前项目代码默认启动standalone模式,不需要依赖任何服务端和存储,能够简单快速的实现单机的录制回放, 控制单机模式的开关在~/.sandbox-module/cfg/repeater.properties 配置文件的 repeat.standalone.mode=true,开启或关闭单机工作模式,关闭单机模式后,配置拉取/消息投递等都依赖repeater.properties中配置的具体url;如不想通过http拉取和消息投递的也可以自己实现BroadcasterConfigManager。稍后我们会公布一份录制回放所需的完整架构图以及jvm-sandbox-repeater在整个体系中的位置供大家工程使用做参考。

 编译源码部署:

 代码结构

[root@k8s-worker27-65 jvm-sandbox-repeater]# ls
bin   hessian-lite  pom.xml    repeater-aide    repeater-console  repeater-plugin-api   repeater-plugins  travis.sh
docs  LICENSE       Readme.md  repeater-client  repeater-module   repeater-plugin-core  target
[root@k8s-worker27-65 jvm-sandbox-repeater]# ls bin/
bootstrap.sh  install-local.sh     package.sh            repeater-logback.xml  sandbox-1.3.3-bin.tar
health.sh     install-repeater.sh  repeater-config.json  repeater.properties

 standalone模式,repeat.standalone.mode=true

[root@k8s-worker27-65 jvm-sandbox-repeater]# git cloen https://github.com/alibaba/jvm-sandbox-repeater.git[root@k8s-worker27-65 jvm-sandbox-repeater]# pwd
/root/work/traffic/jvm-sandbox-repeater
[root@k8s-worker27-65 jvm-sandbox-repeater]# cat bin/repeater.properties 
# 录制消息投递地址
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# 心跳上报配置
repeat.heartbeat.url=http://127.0.0.1:8001/module/report.json# 是否开启脱机工作模式
repeat.standalone.mode=true# 是否开启spring advice拦截
repeat.spring.advice.switch=false;

由于https://github.com/alibaba/jvm-sandbox-repeater/releases/download/v1.0.0/sandbox-1.3.3-bin.tar 下载费劲,我先现在了然后改成一下脚本不用每次下载

[root@k8s-worker27-65 jvm-sandbox-repeater]# cat bin/install-local.sh 
#!/usr/bin/env bash# repeater's target dir
REPEATER_TARGET_DIR=../target/repeater# exit shell with err_code
# $1 : err_code
# $2 : err_msg
exit_on_err()
{[[ ! -z "${2}" ]] && echo "${2}" 1>&2exit ${1}
}# package
sh ./package.sh || exit_on_err 1 "install failed cause package failed"# extract sandbox to ${HOME}
#curl -s https://github.com/alibaba/jvm-sandbox-repeater/releases/download/v1.0.0/sandbox-1.3.3-bin.tar | tar xz -C ${HOME} || exit_on_err 1 "extract sandbox failed"
cat sandbox-1.3.3-bin.tar | tar xz -C ${HOME} || exit_on_err 1 "extract sandbox failed"# copy module to ~/.sandbox-module
mkdir -p ${HOME}/.sandbox-module || exit_on_err 1 "permission denied, can not mkdir ~/.sandbox-module"
cp -r ${REPEATER_TARGET_DIR}/* ${HOME}/.sandbox-module  || exit_on_err 1 "permission denied, can not copy module to ~/.sandbox-module"

快速开始

1. 本地standalone工作(剥离服务端和存储,本机实现录制/回放)

step0 安装sandbox/启动bootstrap
[root@k8s-worker27-65 jvm-sandbox-repeater]# cd bin
[root@k8s-worker27-65 jvm-sandbox-repeater]# ./bootstrap.sh

安装后的结构:

[root@k8s-worker27-65 .sandbox-module]# ls /root/sandbox/
bin  cfg  example  install-local.sh  lib  module  provider  sandbox-module
[root@k8s-worker27-65 .sandbox-module]# ls /root/.sandbox-module/
cfg  plugins  repeater-bootstrap.jar  repeater-module.jar

启动命令:也可以自己手动启动

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -javaagent:/root/sandbox/lib/sandbox-agent.jar=server.port=8820\;server.ip=0.0.0.0 -Dapp.name=jettopro -Dapp.env=sit  -jar  /root/.sandbox-module/repeater-bootstrap.jar

java
-javaagent:${HOME}/sandbox/lib/sandbox-agent.jar=server.port=${repeater 启动端口}\;server.ip=0.0.0.0 \
-Dapp.name=${录制应用名} \
-Dapp.env=${录制环境} \
-jar application.jar

正常启动的是这个应用程序: 

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000  -jar  /root/.sandbox-module/repeater-bootstrap.jar

录播:

[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">JAVA是世界上最好的语言!</h1>

回放

curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId-X=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">Python是世界上最好的语言!</h1>

 此时回放是有问题的,因为没有监听自己的repeater-bootstrap.jar这个应用,监听方式有两种方

1.javaagent方式

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -javaagent:/root/sandbox/lib/sandbox-agent.jar=server.port=8820\;server.ip=0.0.0.0 -Dapp.name=jettopro -Dapp.env=sit  -jar  /root/.sandbox-module/repeater-bootstrap.jar

2.attach方式,先获取pid然后监听

[root@k8s-worker27-65 ~]# ps -ef |grep java
root     16713 13435 99 10:55 pts/1    00:00:33 java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -jar /root/.sandbox-module/repeater-bootstrap.jar

 监听:

[root@k8s-worker27-65 ~]# cd ~/sandbox/bin/
[root@k8s-worker27-65 bin]# ls
sandbox.sh
[root@k8s-worker27-65 bin]# ./sandbox.sh -p 16713 -P 12580
cat: /root/.sandbox.token: 没有那个文件或目录NAMESPACE : defaultVERSION : 1.3.3MODE : ATTACHSERVER_ADDR : 0.0.0.0SERVER_PORT : 12580UNSAFE_SUPPORT : ENABLESANDBOX_HOME : /root/sandbox/bin/..SYSTEM_MODULE_LIB : /root/sandbox/bin/../moduleUSER_MODULE_LIB : /root/sandbox/sandbox-module;~/.sandbox-module;SYSTEM_PROVIDER_LIB : /root/sandbox/bin/../providerEVENT_POOL_SUPPORT : DISABLE

 然后就是可以开始录制和回放了

step1 开始录制

[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">C#是世界上最好的语言!</h1>[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">C++是世界上最好的语言!</h1>[root@k8s-worker27-65 ~]#

是不是看到了C++是世界上最好的语言;我们希望让这一刻永远定格;访问链接时,repeater插件通过Repeat-TraceId=127000000001156034386424510000ed,唯一追踪到了这一次请求,后台服务返回了C++是世界上最好的语言!,repeater把画面定格在了这一秒并将结果和127000000001156034386424510000ed绑定

step2 开始回放
[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId-X=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">C++是世界上最好的语言!</h1>[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId-X=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">C++是世界上最好的语言!</h1>[root@k8s-worker27-65 ~]# curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId-X=127000000001156034386424510000ed'
<h1 align="center" style="color:red;margin-top:300px">C++是世界上最好的语言!</h1>[root@k8s-worker27-65 ~]#

无论我们多少次访问这个地址,都将返回Repeat-TraceId=127000000001156034386424510000ed绑定的录制信息C++是世界上最好的语言!;如果重新访后又会将最新的返回结果绑定到Repeat-TraceId=127000000001156034386424510000ed(为了快速演示,将链路追踪的标志提到参数中进行透传了)

RegressController中提供了更多的测试用例,包括异步servlet、多线程调用、复杂结构返回对象,可以根据slogan类似的方式进行测试。

简单揭秘:/regress/slogan接口调用了RegressServiceImpl#slogan方法

private AtomicInteger sequence = new AtomicInteger(0);private String[] slogans = new String[]{"JAVA", "Python", "PHP", "C#", "C++", "Javascript", "GO"};public String slogan() {return slogans[sequence.getAndIncrement() % slogans.length] + "是世界上最好的语言!";
}

仔细查看该方法代码会发现,每次请求时都会返回不同的语言,为什么回放时每次都返回同样的结果呢?原因很简单,我们对RegressServiceImpl#slogan进行了mock,在回放时开启了mock能力,调用slogan的BEFORE事件时找到了合适值,直接利用ProcessControlException.throwReturnImmediately进行了直接返回,RegressServiceImpl的第72行代码在mock回放时永远不会走到。得益于在repeater-config.json中开启了java插件并且默认拦截了RegressServiceImpl#slogan方法,录制slogan时同时录制java子调用

想要知道应用层面发生了什么吗?请看《Slogan Demo究竟发生了什么》

 不编译非源码部署:

[root@k8s-worker27-65 bin]# ls sandbox-1.3.3-bin.tar repeater-stable-bin.tar 
repeater-stable-bin.tar  sandbox-1.3.3-bin.tar

1. sandbox-1.3.3-bin.tar:https://github.com/alibaba/jvm-sandbox-repeater/releases/download/v1.0.0/sandbox-1.3.3-bin.tar

1.1)这个是官网下载的解压后:

[root@k8s-worker27-65 ~]# ls sandbox
bin  cfg  example  install-local.sh  lib  module  provider  sandbox-module

1.2 )配置文件:

[root@k8s-worker27-65 sandbox]# cat cfg/sandbox.properties  |grep -v "#" |grep -v "^$"
user_module=/root/sandbox-module;
server.charset=UTF-8
unsafe.enable=true

user_module=/root/sandbox-module;  配置为sandbox-module所在的路径即可

2. repeater-stable-bin.tar 自己编译或官网下载都可以 

https://github.com/alibaba/jvm-sandbox-repeater/releases/download/v1.0.0/repeater-stable-bin.tar

2.1)解压之后:

[root@k8s-worker27-65 ~]# ls sandbox-module/
cfg  plugins  repeater-bootstrap.jar  repeater-data  repeater-module.jar

2.2)配置文件:

[root@k8s-worker27-65 cfg]# cat repeater.properties  |grep -v "#" |grep -v "^$"
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
repeat.heartbeat.url=http://127.0.0.1:8001/module/report.json
repeat.standalone.mode=true
repeat.spring.advice.switch=false;

repeat.standalone.mode=true 
【1】true:就是本地模式不需要数据库存在录播文件,在本地目录中存储[root@k8s-worker27-65 sandbox-module]# ls sandbox-module/repeater-data/record/127000000001156034386424510000ed

【2】false:需要数据库mysql进行存储

录制自己的应用:

[root@k8s-worker27-65 aaaa]# cat repeater/cfg/repeater-config.json
{"useTtl" : true,"degrade" : false,"exceptionThreshold" : 1000,"sampleRate" : 10000,"pluginsPath" : null,"httpEntrancePatterns" : [ "^/greeting.*$" ],"javaEntranceBehaviors" : [],"javaSubInvokeBehaviors" : [ {"classPattern" : "hello.GreetingController","methodPatterns" : [ "greeting" ],"includeSubClasses" : false} ],"pluginIdentities" : [ "http", "java-entrance", "java-subInvoke", "mybatis", "ibatis" ],"repeatIdentities" : [ "java", "http" ]
}

自己应用的pid:26362 

[root@k8s-worker27-65 target]# ps -ef |grep java
root     26200 13435 11 14:20 pts/1    00:01:00 java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -javaagent:/opt/aaaa/sandbox/lib/sandbox-agent.jar=server.port=8820;server.ip=0.0.0.0 -Dapp.name=jettopro -Dapp.env=sit -jar /opt/aaaa/repeater/repeater-bootstrap.jar
root     26362 13398  5 14:21 pts/0    00:00:22 java -jar gs-rest-service-0.1.0.jar

1)attach自己的pid进行监听

[root@k8s-worker27-65 bin]# pwd
/opt/aaaa/sandbox/bin
[root@k8s-worker27-65 bin]# ./sandbox.sh -p 26362 -P 12501NAMESPACE : defaultVERSION : 1.3.3MODE : ATTACHSERVER_ADDR : 0.0.0.0SERVER_PORT : 12501UNSAFE_SUPPORT : ENABLESANDBOX_HOME : /opt/aaaa/sandbox/bin/..SYSTEM_MODULE_LIB : /opt/aaaa/sandbox/bin/../moduleUSER_MODULE_LIB : /opt/aaaa/sandbox/sandbox-module;/opt/aaaa/repeater;SYSTEM_PROVIDER_LIB : /opt/aaaa/sandbox/bin/../providerEVENT_POOL_SUPPORT : DISABLE

2)测试自己的服务是否可以录制:因为是录制id一直在增加

[root@k8s-worker27-65 repeater]# pwd
/opt/aaaa/repeater
[root@k8s-worker27-65 repeater]# ls
cfg  plugins  repeater-bootstrap.jar  repeater-module.jar
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId=127000000001156034386424510000ea'
{"id":25,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId=127000000001156034386424510000eb'
{"id":26,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId=127000000001156034386424510000ec'
{"id":27,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId=127000000001156034386424510000ed'
{"id":28,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId=127000000001156034386424510000ee'
{"id":29,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]#
[root@k8s-worker27-65 repeater]# ls
cfg  plugins  repeater-bootstrap.jar  repeater-data  repeater-module.jar有这个 repeater-data 目录说明录制成功

回放:多次执行一直都是id为25没有增加,说明定在了id为25这个条目上,可以对id=25进行多次回放,也可以选在id进行回放。但是id没有进行录制过的进行回放是回放不了的如id是30的

[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ea'
{"id":25,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000eb'
{"id":26,"content":"Hello, jettech01!"}
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ec'
{"id":27,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ed'
{"id":28,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ee'
{"id":29,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ef'
{"id":30,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 
[root@k8s-worker27-65 repeater]# curl -s 'http://localhost:8080/greeting?name=jettech01&Repeat-TraceId-X=127000000001156034386424510000ea'
{"id":25,"content":"Hello, jettech01!"}[root@k8s-worker27-65 repeater]# 

https://github.com/alibaba/jvm-sandbox-repeater/blob/master/docs/user-guide-cn.md#2-%E5%BF%AB%E9%80%9F%E5%BD%95%E5%88%B6%E8%87%AA%E5%B7%B1%E5%BA%94%E7%94%A8

这篇关于jvm-sandbox-repeater 精简版部署之standalone模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/494565

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听