前言
在上文中我们分析了sandbox-jvm(以下简称sandbox)的核心源码,了解了sandbox实现类增强的原理。并且了解了sandbox的模块化加载能力,repeater作为一个独立的模块,其基于sandbox的能力实现了流量的录制和回放。下面我们从repeater的软件结构、录制过程、回放过程三个方面来分析其源码。
软件结构
代码角度
jvm-sandbox-repeater
hessian-lite: 序列化服务
repeater-aide: 辅助工具
repeater-client: spring ApplicationContext获取工具
repeater-console: 控制台能力
repeater-module: 可以被sandbox加载的模块,用于流量录制与回放
repeater-plugin-api:repeater可以实现和扩展的接口
repeater-plugin-core:repeater插件的核心能力和管理能力
repeater-plugins:repeater默认实现的插件
运行角度
repeater作为sandbox一个子模块加载,进行流量录制发送console,console存储流量并且,调用repeater将流量在目标jvm上回放
流量录制
插件的加载
代码结构中已经介绍到repeater-module负责流量的录制工作,我们从repeater-module模块中,RepeaterModule.class来进行分析。
RepeaterModule实现了ModuleLifecycle接口,在sandbox进行模块加载时,对于实现该接口的实例会一次执行其onLoad方法、onActive方法、onCompleted方法,一起来看下onCompleted方法:
- 在线程池中执行,配置拉取,pullConfig实际上就是调用console提供的接口能力
- 根据配置进行初始化
- 启动心跳检测
public void loadCompleted() {
ExecutorInner.execute(new Runnable() {
@Override
public void run() {
configManager = StandaloneSwitch.instance().getConfigManager();
broadcaster = StandaloneSwitch.instance().getBroadcaster();
invocationListener = new DefaultInvocationListener(broadcaster);
RepeaterResult<RepeaterConfig> pr = configManager.pullConfig();
if (pr.isSuccess()) {
log.info("pull repeater config success,config={}", pr.getData());
ClassloaderBridge.init(loadedClassDataSource);
initialize(pr.getData());
}
}
});
heartbeatHandler = new HeartbeatHandler(configInfo, moduleManager);
heartbeatHandler.start();
}
来看下初始化过程:
- 根据配置装载插件,注意invokePlugin.watch的实现,这里最终就是调用了BuildingForBehavior.onWatch,如果看过上一篇文章就知道,sandbox就是在这个阶段实现类增强
String pluginsPath;
if (StringUtils.isEmpty(config.getPluginsPath())) {
pluginsPath = PathUtils.getPluginPath();
} else {
pluginsPath = config.getPluginsPath()