平台的CSM子系统里管理了N个密码设备的配置信息,后面需要启动对应的微服务与密码设备进行对接。对接的前提条件时设备的配置信息准确无误,所以需要对设备的配置信息进行连通性测试。连通性测试的方式有很多,比如可以启动一个真实的微服务与之对接、或者在某个方法里直接调用设备的API,这里我们采用后者。
由于设备类型众多,所以将测试连通性的方法统一写到一个Connectivity项目中,该项目提供连通性测试的具体方法实现,并暴露出url供CSM调用,然后将其打包为jar,比如命名为test.jar.在CSM子系统的界面上进行测试连通性操作时,使用Runtime.exec("java -jar test.jar &")来启动。然而我们使用的Docker Swarm 或kubernetes两套部署环境,CSM本身就是一个docker容器,然后在docker容器内部又启动一个jar进程。虽然可以将test.jar启动,但是使用SpringBoot自带的actuator/shutdown方法无法将其进程立即关闭掉,通过命令查看到该进程一直处于wait或者listen的状态。但是测试连通性里的测试方法只能初始化一次,这就导致了我们必须调用完test.jar提供的方法后必须销毁后重新启动test.jar.
RUN apt-get update
RUN apt-get install net-tools
RUN apt-get install -y procps
/**
* 执行jar
*
* @return boolean
*/
public boolean runJar() {
Runtime runtime = Runtime.getRuntime();
try {
String cmd = "java -jar ";
File jarFile = new File(apolloConfigParams.getJarFilePath());
if (jarFile.exists()) {
logger.info(apolloConfigParams.getJarFilePath() + " file is exist");
cmd += apolloConfigParams.getJarFilePath() + " &";
logger.info("执行jar命令为:{}", cmd);
} else {
logger.error(apolloConfigParams.getJarFilePath() + " file is not exist !!!");
return false;
}
Process msg = runtime.exec(cmd);
//睡眠8s,否则jar未完全启动,导致后续调用方法失败
Thread.sleep(8000);
return msg.isAlive();
} catch (Exception e) {
logger.error("执行jar失败,{}", e);
}
return false;
}
/**
* 关闭jar
*/
public void shutdownJar() {
String cmd = "ps -ef | grep CsspConnectivity | grep -v grep | awk '{print $2}' |xargs kill -9";
String[] commands = {"/bin/sh", "-c", cmd};
String cmdStr = JSON.toJSONString(commands);
try {
Runtime runtime = Runtime.getRuntime();
runtime.exec(commands);
logger.info("执行命令【{}】成功", cmdStr);
} catch (IOException e) {
logger.error("执行命令【{}】失败,{}", cmdStr, e);
}
}
最开始执行shutdownJar的方法是没有添加上/bin/sh -c 导致一直无法关闭jar进程。加上后成功解决问题。