通过官方提供的 repeater 的下载链接,并不能够在sandbox启动时,加载进行,我们可以看下sandbox的日志截图
但是如果通过源码的repeater进行安装后,就能够成功加载到repeater。
这是个很奇怪的问题,想要分析这个,我们就要确认下通过官方的脚本安装跟源码安装的差异在哪了。
官方的shell脚本
#!/usr/bin/env bashtypeset SANDBOX_HOME=${HOME}/sandboxtypeset MODULE_HOME=${HOME}/.sandbox-module# exit shell with err_code
# $1 : err_code
# $2 : err_msg
exit_on_err()
{[[ ! -z "${2}" ]] && echo "${2}" 1>&2exit ${1}
}main(){echo "====== begin to install sandbox and repeater module ======";echo "====== step 0 begin to download sandbox package ======";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"echo "====== step 1 begin to download repeater module package ======";if [ ! -d ${MODULE_HOME} ]; thenmkdir -p ${MODULE_HOME} || exit_on_err 1 "permission denied mkdir ${MODULE_HOME}"ficurl -s https://github.com/alibaba/jvm-sandbox-repeater/releases/download/v1.0.0/repeater-stable-bin.tar | tar xz -C ${MODULE_HOME} || exit_on_err 1 "extract repeater failed"echo "====== install finished ======";
}main
从上面可以看出来,其实就是下载两个文件,分别解压到对应的目录下就好了。
那我们再看下通过repeater源码进行执行 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 x -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"
我们可以看到这里的过程其实就是先进行打包repeater, 然后在下载sandbox, 再将打包后的repeater的内容,复制一份到 sandbox-module
目录下。这里其实是有差异的,一个是解压压缩包,一个是直接复制目录的情况。
这里如果细致的话,就会发现一个明显不一样的地方了。
通过官方的shell脚本安装以后,得到的 .sandbox-module
目录下是一个repeater
的目录
而 通过源码安装得到的其实是不一样的
但是官方的得到的目录进行的一个层级一个 得到的就是相同的目录了.
这就是问题的根因了,但是为什么多一个目录,就导致没有办法被加载呢,其实这个我们可以尝试去看下sandbox的逻辑。
ModuleLibLoader.java
private File[] listModuleJarFileInLib() {final File[] moduleJarFileArray = toModuleJarFileArray();Arrays.sort(moduleJarFileArray);logger.info("loading module-lib={}, found {} module-jar files : {}",moduleLibDir,moduleJarFileArray.length,join(moduleJarFileArray, ","));return moduleJarFileArray;
}
我们可以知道,加载module-lib成功就会有这样子的内容打印,所以其实关键就是
private File[] toModuleJarFileArray() {if (moduleLibDir.exists()&& moduleLibDir.isFile()&& moduleLibDir.canRead()&& StringUtils.endsWith(moduleLibDir.getName(), ".jar")) {return new File[]{moduleLibDir};} else {return convertFileCollectionToFileArray(listFiles(moduleLibDir, new String[]{"jar"}, false));}
}
listFiles(moduleLibDir, new String[]{"jar"}, false)
是列出对应目录下所有jar包的问题,但是关键是第三个参数是false,其实就是不递归遍历,所以它只会获取到第一层级的目录,所以这就导致了如果目录多一个repeater以后,就没有办法,加载repeater了。