无印良品设计总监原研哉写过一本书,书名叫做《设计中的设计》,大致的意思是在提醒我们:每个人都可以做一个设计师,因为你设计的不仅仅是一般意义上的“设计”,还有你的生活。
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实现。
思考与展望
记录下这些类的用法,知道有这样的一个东西能做这样的事情。
但只适合做一些公司内部使用的平台,如果要对外使用,需要考虑的点还有很多,比如海量日志的存取,触发插件的幂等性,平台集群部署等等。