docker容器内部执行jar调用jar提供的方法后kill该进程

需求背景

平台的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.

解决办法

1、修改Dockerfile,打包时添加相关命令

RUN apt-get update
RUN apt-get install net-tools
RUN apt-get install -y procps

2、启动jar,执行完命令后需要sleep一会,否则直接调用jar的方法会直接报Connection refused

/**
     * 执行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;
    }

2、调用jar提供的方法后销毁jar进程

/**
     * 关闭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进程。加上后成功解决问题。

你可能感兴趣的:(菜鸟每天进步一点点)