程序中的程序

65 阅读2分钟

无印良品设计总监原研哉写过一本书,书名叫做《设计中的设计》,大致的意思是在提醒我们:每个人都可以做一个设计师,因为你设计的不仅仅是一般意义上的“设计”,还有你的生活。

designer与coder的共同点在于都是脑力体力结合,都需要一些创造性思维。引出今日话题——作为一个code artist,如何去设计你的程序?以及emmm...程序中的程序?

背景

最近在做了一个公司内部使用的插件管理平台,平台目标是运行同一标准的镜像插件,并且实现插件热插拔、插件多版本控制、插件日志管理、插件配置覆盖等等。插件里具体业务逻辑交给下游业务团队去实现(需遵循平台插件规范)。依托平台达到业务解耦,插件可扩展,实现部门内部数据流转的降本增效。

ProcessBuilder

怎么去通过平台去运行插件的程序呢,可以用ProcessBuilder。

该类下面Windows与Linux的入参格式可能会不一样,记录一下:

         // windows下的调试代码,模拟打开cmd窗口输入第三方jar包启动
//        List<String> params = new ArrayList<>();
//        params.add("cmd.exe");
//        params.add("/c");
//        params.add("java -jar D:\\gitRepo\\xxx.jar ");
//        ProcessBuilder processBuilder = new ProcessBuilder(params);
        // Linux下的调试代码,模拟执行/aaa/bbb目录下的第三方jar包启动
        ProcessBuilder processBuilder = new ProcessBuilder();
        //Linux 下设置脚本运行目录
        processBuilder.directory("/aaa/bbb");
        //设置命令
        processBuilder.command("java", "-jar", "/xxx.jar");
        log.info(processBuilder.directory().getAbsolutePath());
        log.info(processBuilder.environment().toString());
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        // 打印第三方jar的控制台日志
        while ((line = br.readLine()) != null) {
            log.info(line);
        }
        int exitCode = process.waitFor();
        log.info("exitCode = {}", exitCode);          

DockerClient

项目里面的插件是用的docker镜像,怎么让平台去触发docker镜像的操作呢,包括启动容器,停止容器,获取容器日志等等,可以考虑用DockerClient

<dependency>
	<groupId>com.github.docker-java</groupId>
	<artifactId>docker-java</artifactId>
	<version>3.2.13</version>
</dependency>

比如创建DockerClient客户端连接:

/**
 * docker client 客户端连接
 *
 * @param dockerInstance
 * @return com.github.dockerjava.api.DockerClient
 **/
public synchronized DockerClient connectDocker(String dockerInstance) {
         dockerInstance = "tcp://127.0.0.1:2375";
	long cost = System.currentTimeMillis();
	try {
		DockerClient dockerClient = DockerClientBuilder.getInstance(
				DefaultDockerClientConfig.createDefaultConfigBuilder()
						.withDockerHost(dockerInstance)
						.withRegistryUrl("http://127.0.0.1:2375")
						.build()).build();
		dockerClient.infoCmd().exec();
		return dockerClient;
	} catch (Exception ex) {
		log.info("init docker client error ");
		log.warn("Docker is not installed on this server.[{}]", ex.getMessage());
		return null;
	} finally {
		log.info("init dockerClient cost {} ms", System.currentTimeMillis() - cost);
	}
}

其他在对应Linux环境下的docker操作都可以尝试用对应API实现。

思考与展望

记录下这些类的用法,知道有这样的一个东西能做这样的事情。

但只适合做一些公司内部使用的平台,如果要对外使用,需要考虑的点还有很多,比如海量日志的存取,触发插件的幂等性,平台集群部署等等。