modules/mainPart/pom.xml
@@ -47,6 +47,11 @@ <artifactId>batik-all</artifactId> <version>1.16</version> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>4.1.0</version> </dependency> </dependencies> <!-- pom.xml --> modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/controller/SimulatAssessController.java
@@ -6,6 +6,11 @@ import cn.hutool.json.XML; import com.fasterxml.jackson.databind.ObjectMapper; import com.zt.common.annotation.LogOperation; import com.zt.common.annotation.QueryParam; import com.zt.common.constant.Constant; import com.zt.common.db.query.QueryFilter; import com.zt.common.exception.RenException; import com.zt.common.servlet.PageResult; import com.zt.common.servlet.Result; import com.zt.common.validator.AssertUtils; import com.zt.common.validator.ValidatorUtils; @@ -16,7 +21,10 @@ import com.zt.life.modules.mainPart.taskReliability.model.*; import com.zt.life.modules.mainPart.taskReliability.service.SimulatAssessService; import com.zt.life.modules.mainPart.taskReliability.service.TaskService; import com.zt.life.modules.mainPart.utils.OSUtils.ProcessUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -26,6 +34,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; import java.io.File; import java.io.FileInputStream; @@ -95,8 +104,21 @@ if (result2) return Result.ok(); else return Result.error(); return Result.error("算法库计算失败!"); } @GetMapping("process") @ApiOperation("获取算法库进程信息") @ApiImplicitParams({ @ApiImplicitParam(name = Constant.Q.PAGE, value = Constant.QV.PAGE, required = true, dataType = Constant.QT.INT), @ApiImplicitParam(name = Constant.Q.LIMIT, value = Constant.QV.LIMIT, required = true, dataType = Constant.QT.INT), @ApiImplicitParam(name = "isAlive", value = "存活", dataType = Constant.QT.Boolean), }) public PageResult<SimulatAssess> process(@ApiIgnore @QueryParam QueryFilter queryFilter) { List<SimulatAssess> page = simulatAssessService.process(queryFilter); return PageResult.ok(page); } @PostMapping("getResultXML") public Result<SimulaDataDto> getResultXML(@RequestBody SimulatAssess simulatAssess) { @@ -146,26 +168,77 @@ String progress2 = ""; String key = null; if (taskList.length == 1) { key = taskList[0].toString() + simulatAssessService.RELIA_SIM_TASK_TYPE_PROGRESS; Long taskId = taskList[0]; SimulatAssess simulatAssess = simulatAssessService.get(taskId); boolean isProcessAlive = ProcessUtils.isProcessAlive(simulatAssess.getPid()); key = taskId.toString() + simulatAssessService.RELIA_SIM_TASK_TYPE_PROGRESS; progress2 = (String) redisTemplate.opsForValue().get(key); if (progress2 == null) progress2 = "0"; progress = Integer.parseInt(progress2); if (progress == null) progress = 0; updateSimulateAssess(simulatAssess, isProcessAlive, progress); if (progress < 100 && !isProcessAlive) { logger.error("算法库进程在计算途中异常终止了:taskId="+taskId+" pid="+simulatAssess.getPid()+" progress="+progress); simulatAssessService.deleteSimInfoInRedis(taskId); return Result.error("算法库进程在计算途中异常终止了!"); } if (progress == 100) { //simulatAssessService.deleteSimInfoInRedis(taskId); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } isProcessAlive = ProcessUtils.isProcessAlive(simulatAssess.getPid()); simulatAssess.setProcessIsAlive(isProcessAlive); simulatAssessService.update(simulatAssess); // simulatAssessService.deleteSimInfoInRedis(taskId); } } else { for (Long taskId : taskList) { int progTmp = 0; SimulatAssess simulatAssess = simulatAssessService.get(taskId); boolean isProcessAlive = ProcessUtils.isProcessAlive(simulatAssess.getPid()); key = taskId.toString() + simulatAssessService.RELIA_SIM_TASK_TYPE_PROGRESS; progress2 = (String) redisTemplate.opsForValue().get(key); progress = progress + Integer.parseInt(progress2); if (progress2 == null) progress2 = "0"; progTmp = Integer.parseInt(progress2); updateSimulateAssess(simulatAssess, isProcessAlive, progTmp); if (progTmp < 100 && !isProcessAlive) { logger.error("算法库进程在计算途中异常终止了:taskId="+taskId+" pid="+simulatAssess.getPid()+" progress="+progTmp); // simulatAssessService.deleteSimInfoInRedis(taskId); return Result.error("算法库进程在计算途中异常终止了!"); } if (progTmp == 100) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } isProcessAlive = ProcessUtils.isProcessAlive(simulatAssess.getPid()); simulatAssess.setProcessIsAlive(isProcessAlive); simulatAssessService.update(simulatAssess); // simulatAssessService.deleteSimInfoInRedis(taskId); } progress = progress + progTmp; } progress = progress / taskList.length; if (progress == 100) { //simulatAssessService.deleteSimInfoInRedis(taskId); } } return Result.ok(progress.toString()); } private void updateSimulateAssess(SimulatAssess simulatAssess, boolean isProcessAlive, int progress) { if (!isProcessAlive) { simulatAssess.setProcessIsAlive(false); simulatAssess.setProgress(progress); simulatAssess.setProcessEndTime(new Date()); simulatAssessService.update(simulatAssess); } else { if (simulatAssess.getProgress() != progress) { simulatAssess.setProgress(progress); simulatAssessService.update(simulatAssess); } } } @GetMapping("ReliabilityWeakness") @@ -186,6 +259,16 @@ return Result.ok(data); } @GetMapping("killProcess") public Result<SchemeComparDto> killProcess(@RequestParam("taskId") Long taskId) { SimulatAssess simulatAssess = simulatAssessService.get(taskId); ProcessUtils.killProcess(simulatAssess.getPid()); boolean isProcessAlive = ProcessUtils.isProcessAlive(simulatAssess.getPid()); simulatAssess.setProcessIsAlive(isProcessAlive); simulatAssessService.update(simulatAssess); return Result.ok(); } @PutMapping @ApiOperation("修改") @LogOperation("修改") modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dao/SimulatAssessDao.java
@@ -47,4 +47,6 @@ List<verifyDto> getNode(Long modelId); Integer getVoteNum(Long id); List<SimulatAssess> getProcessList(Map<String, Object> params); } modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/SimulatAssess.java
@@ -2,9 +2,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.zt.common.constant.Bool; import com.zt.common.entity.BusiEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -23,9 +21,11 @@ public class SimulatAssess extends BusiEntity { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "产品节点ID") private Long productId; @ApiModelProperty(value = "名称") private String name; @ApiModelProperty(value = "总体任务模型ID") private Long taskModelId; @@ -51,5 +51,21 @@ @ApiModelProperty(value = "传给算法库的xml") private String xml; private String name; @ApiModelProperty(value = "算法库进程ID") private Long pid; @ApiModelProperty(value = "算法库进程是否存活") private Boolean processIsAlive; @ApiModelProperty(value = "启动命令行") private String commandLine; @ApiModelProperty(value = "计算进度") private Integer progress; @ApiModelProperty(value = "算法库进程启动时间") private Date processStartTime; @ApiModelProperty(value = "算法库进程终止时间") private Date processEndTime; } modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/service/SimulatAssessService.java
@@ -5,6 +5,7 @@ import cn.hutool.json.XML; import com.fasterxml.jackson.databind.ObjectMapper; import com.spire.pdf.tables.table.convert.Convert; import com.zt.common.db.query.QueryFilter; import com.zt.common.exception.RenException; import com.zt.common.service.BaseService; import com.zt.common.servlet.Result; @@ -24,6 +25,7 @@ import com.zt.life.modules.mainPart.taskReliability.dto.TaskPhaseConstraintDto; import com.zt.life.modules.mainPart.taskReliability.model.*; import com.zt.life.modules.mainPart.utils.GetStringSpace; import com.zt.life.modules.mainPart.utils.OSUtils.ProcessUtils; import io.swagger.models.auth.In; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -115,7 +117,6 @@ Map<Integer, String> templetsStrMap2 = new HashMap<>(); private JSONObject xmlJSONObj; /** * 分页查询 @@ -655,7 +656,6 @@ return result; } @Transactional(rollbackFor = Exception.class) public Boolean simulate(SimulatAssess simulatAssess) { Boolean result = false; // 2. 组装供算法库仿真的模型xml @@ -665,6 +665,11 @@ result = callReliaSimLib(simulatAssess); return result; } public List<SimulatAssess> process(QueryFilter queryFilter) { List<SimulatAssess> page = baseDao.getProcessList(queryFilter.getParams()); return queryFilter.getPageList(page); } private Boolean callReliaSimLib(SimulatAssess simulatAssess) { @@ -690,6 +695,8 @@ } else { throw new RenException("暂不支持该操作系统,进行启动算法库计算!"); } long pid = ProcessUtils.getProcessId(process); logger.info("算法库PID:" + pid); is = process.getInputStream(); // 以命令行方式调用算法库时,接口约定返回的结果是utf-8编码 br = new BufferedReader(new InputStreamReader(is, "utf-8")); @@ -700,6 +707,8 @@ ReliaSimLibResult rtn = com.alibaba.fastjson.JSONObject.parseObject(line, ReliaSimLibResult.class); if ("0".equals(rtn.getCode())) { logger.info("启动可靠性仿真评估算法库成功。"); newProcess(simulatAssess, pid, command); update(simulatAssess); result = true; } else { String errorMsg = rtn.getErrorMsg(); @@ -730,6 +739,14 @@ return result; } public void newProcess(SimulatAssess simulatAssess, long pid, String command) { simulatAssess.setPid(pid); simulatAssess.setCommandLine(command); simulatAssess.setProcessIsAlive(true); simulatAssess.setProcessStartTime(new Date()); simulatAssess.setProgress(0); } private void setParamToRedis(SimulatAssess simulatAssess) { String key = simulatAssess.getId().toString() + RELIA_SIM_TASK_TYPE_SIMULATION; logger.info("redis key:" + key); modules/mainPart/src/main/java/com/zt/life/modules/mainPart/utils/OSUtils/Kernel32.java
New file @@ -0,0 +1,9 @@ package com.zt.life.modules.mainPart.utils.OSUtils; import com.sun.jna.Library; import com.sun.jna.Native; public interface Kernel32 extends Library{ public static Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class); public long GetProcessId(Long hProcess); } modules/mainPart/src/main/java/com/zt/life/modules/mainPart/utils/OSUtils/ProcessUtils.java
New file @@ -0,0 +1,78 @@ package com.zt.life.modules.mainPart.utils.OSUtils; import com.zt.common.exception.RenException; import java.io.BufferedReader; import java.io.InputStreamReader; public class ProcessUtils { public static long getProcessId(Process process) { long pid = -1; java.lang.reflect.Field field = null; try { if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) { field = process.getClass().getDeclaredField("handle"); } else if (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1) { field = process.getClass().getDeclaredField("pid"); } else { throw new RenException("暂不支持该操作系统:获取进程号"); } field.setAccessible(true); pid = Kernel32.INSTANCE.GetProcessId((Long)field.get(process)); } catch (Exception e) { e.printStackTrace(); } return pid; } public static void killProcess(long pid) { try { Process process = null; if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) { process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", "taskkill /PID "+pid+" /T /F"}); } else if (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1) { process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "kill -9 "+pid}); } else { throw new RenException("暂不支持该操作系统:终止进程!"); } int exitCode = process.waitFor(); } catch (Exception e) { e.printStackTrace(); } } public static boolean isProcessAlive(long pid) { boolean isAlive = false; try { // 根据不同的操作系统,构造不同的命令 String os = System.getProperty("os.name").toLowerCase(); String command; if (os.contains("win")) { // Windows 系统 command = "tasklist /FI \"PID eq " + pid + "\""; } else { // Unix-like 系统 command = "ps -p " + pid; } Process process = Runtime.getRuntime().exec(command); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; // 判断输出中是否包含进程信息 while ((line = reader.readLine()) != null) { if (line.contains(String.valueOf(pid))) { isAlive = true; break; } } reader.close(); } catch (Exception e) { e.printStackTrace(); } return isAlive; } } modules/mainPart/src/main/resources/mapper/taskReliability/SimulatAssessDao.xml
@@ -233,4 +233,15 @@ and vote_num is not null limit 1 </select> <select id="getProcessList" resultType="com.zt.life.modules.mainPart.taskReliability.model.SimulatAssess"> select * from simulat_assess where IS_DELETE = 0 and pid is not null <if test="isAlive"> and process_is_alive=1 </if> order by process_start_time desc </select> </mapper> web/src/views/modules/taskReliability/Process.vue
New file @@ -0,0 +1,87 @@ <template> <zt-dialog ref="dialog" title="算法库进程详情" append-to-body column="3" @close="close" :editAble="false"> <zt-table-wraper :dataForm="queryForm" ref="tableObj" v-slot="{ table }" :page-size="20" :paging="true" @dataLoaded="dataLoaded" query-url="/taskReliability/SimulatAssess/process"> <el-form :inline="true" :model="queryForm" @keyup.enter.native="table.query()"> <el-form-item prop="isAlive" label-width="150px" style="margin-left: 20px"> <el-checkbox v-model="queryForm.isAlive">只看存活</el-checkbox> </el-form-item> </el-form> <el-table ref="table" v-adaptive="{bottomOffset:30}" height="100px" style="font-size: 18px" v-loading="table.dataLoading" :data="table.dataList" border highlight-current-row @selection-change="table.selectionChangeHandle"> <el-table-column align="center" label="序号" prop="index" width="60"> <template slot-scope="scope"> <span v-html="indexFormat(scope.$index)"></span> </template> </el-table-column> <el-table-column prop="pid" label="进程ID" align="center" width="100"/> <el-table-column prop="processIsAlive" label="存活状态" align="center" width="100"> <template v-slot="{ row }"> <span v-if="row.processIsAlive" style="">存活</span> <span v-else>终止</span> </template> </el-table-column> <el-table-column prop="commandLine" label="启动命令行" align="center"/> <el-table-column prop="progress" label="仿真进度" align="center" width="100"/> <el-table-column prop="processStartTime" label="生成时间" align="center" width="200"/> <el-table-column prop="processEndTime" label="终止时间" align="center" width="200"/> <el-table-column width="150" class="han" align="center" :table="table" label="操作"> <template v-slot="{ row }"> <zt-table-button v-if="row.processIsAlive" style="font-size: 18px" type="warning" @click="killProcess(row.id)">强制终止</zt-table-button> </template> </el-table-column> </el-table> </zt-table-wraper> </zt-dialog> </template> <script> export default { data() { return { queryForm: { isAlive: false, }, } }, watch: { 'queryForm.isAlive'() { this.$refs.tableObj.query() }, }, components: { }, mounted() { this.$refs.tableObj.query() }, methods: { init() { }, indexFormat(index) { let page = this.$refs.tableObj.page let limit = this.$refs.tableObj.limit let indexs = limit * (page - 1) + index + 1 return '<span>' + indexs + '</span>' }, async killProcess(id) { if (id) { let param = { taskId: id } let res = await this.$http.get(`/taskReliability/SimulatAssess/killProcess`, {params: param}) this.$refs.tableObj.query() } }, }, } </script> <style> </style> web/src/views/modules/taskReliability/SchemeCompar.vue
@@ -156,11 +156,11 @@ ProductModelTree, }, watch: { percentage() { if (this.percentage === 100) { this.getEcharts(); } } // percentage() { // if (this.percentage === 100) { // this.getEcharts(); // } // } }, methods: { onTreeSelected(data) { @@ -205,18 +205,20 @@ console.log(res.data) this.schemeList = res.data }, getStroke() { if (this.percentage < 100) { let param = { taskList: this.fzIdList } this.$http.get(`/taskReliability/SimulatAssess/getCalcProgress`, {params: param}).then( res => { if (res.data) { this.percentage = parseFloat(res.data) } async getStroke() { let param = { taskList: this.fzIdList } let res = await this.$http.get(`/taskReliability/SimulatAssess/getCalcProgress`, {params: param}) if (res.success) { if (res.data) { this.percentage = parseFloat(res.data) if (this.percentage >= 100) { clearInterval(this.timers) this.percentage = 0 await this.getEcharts(); } ) } } else { clearInterval(this.timers) this.percentage = 0 @@ -233,6 +235,7 @@ simulatFrequency: this.dataForm.simulatFrequency } console.log(this.dataForm.taskModelId, 'this.dataForm.taskModelId') this.percentage = 0 let res = await this.$http.get('/taskReliability/SimulatAssess/SchemeCompar', {params: params}) console.log(res.data, "res") if (res.success) { web/src/views/modules/taskReliability/SimulatAssess.vue
@@ -24,6 +24,9 @@ <zt-form-item style="margin-left: 20px"> <zt-button @click="analyze()">仿真分析</zt-button> </zt-form-item> <zt-form-item style="margin-left: 20px"> <zt-button @click="displayProcess()">查看算法库进程</zt-button> </zt-form-item> </el-form> <el-progress v-if="isShow" :percentage="percentage"></el-progress> <el-col :span="4"> @@ -55,18 +58,20 @@ <el-button type="primary" @click="dialogVisible = false">关 闭</el-button> </div> </el-dialog> <Process ref="process"></Process> </div> </template> <script> import SimulatCurve from "./SimulatCurve"; import ProductModelTree from "../basicInfo/ProductModelTree"; import Process from "./Process"; export default { data() { return { timers: '', timers: null, isSelect: false, isShow: false, percentage: 0, @@ -94,15 +99,16 @@ this.getProductList() }, watch: { percentage() { if (this.percentage === 100) { this.$refs.SimulatCurve.initEcharts(this.dataForm); } } // percentage() { // if (this.percentage === 100) { // this.$refs.SimulatCurve.initEcharts(this.dataForm); // } // } }, components: { ProductModelTree, SimulatCurve, Process, }, methods: { @@ -141,18 +147,20 @@ console.log(res.data) this.taskList = res.data }, getStroke() { if (this.percentage < 100) { let param = { taskList: [this.dataForm.id] } this.$http.get(`/taskReliability/SimulatAssess/getCalcProgress`, {params: param}).then( res => { if (res.data) { this.percentage = parseFloat(res.data) } async getStroke() { let param = { taskList: [this.dataForm.id] } let res = await this.$http.get(`/taskReliability/SimulatAssess/getCalcProgress`, {params: param}) if (res.success) { if (res.data) { this.percentage = parseFloat(res.data) if (this.percentage >= 100) { clearInterval(this.timers) this.percentage = 0 this.$refs.SimulatCurve.initEcharts(this.dataForm); } ) } } else { clearInterval(this.timers) this.percentage = 0 @@ -164,9 +172,10 @@ this.isShow = true let result = await this.$http.get(`/basicInfo/TyProductModel/getUuid`) this.dataForm.id = result.data this.percentage = 0 let res = await this.$http.post('/taskReliability/SimulatAssess/analyze', this.dataForm) if (res.success) { console.log(res.data) console.log(res.data, 'res.data') if (res.data && res.data.length > 0) { this.modelCheckResult = res.data this.dialogVisible = true @@ -174,6 +183,9 @@ this.timers = window.setInterval(this.getStroke, 1000) } } }, displayProcess() { this.$refs.process.$refs.dialog.init() } } }