|
@@ -8,7 +8,6 @@ import api.common.util.JsonUtil;
|
|
|
import api.common.util.StringUtil;
|
|
|
import com.css.simulation.resource.scheduler.mapper.*;
|
|
|
import com.css.simulation.resource.scheduler.pojo.po.*;
|
|
|
-import com.css.simulation.resource.scheduler.pojo.to.KubernetesNodeTO;
|
|
|
import com.css.simulation.resource.scheduler.pojo.to.PrefixTO;
|
|
|
import com.css.simulation.resource.scheduler.service.ProjectService;
|
|
|
import com.css.simulation.resource.scheduler.util.ProjectUtil;
|
|
@@ -25,6 +24,7 @@ import org.springframework.stereotype.Component;
|
|
|
import javax.annotation.Resource;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
|
|
|
@Component
|
|
@@ -33,10 +33,7 @@ public class ProjectConsumer {
|
|
|
|
|
|
@Value("${scheduler.minio-path.project-result}")
|
|
|
String resultPathMinio;
|
|
|
- @Value("${scheduler.linux-path.job-template}")
|
|
|
- String jobTemplate;
|
|
|
- @Value("${scheduler.linux-path.job-yaml}")
|
|
|
- String jobYaml;
|
|
|
+
|
|
|
|
|
|
@Value("${scheduler.host.hostname}")
|
|
|
String hostname;
|
|
@@ -77,10 +74,10 @@ public class ProjectConsumer {
|
|
|
@KafkaListener(groupId = "simulation-resource-scheduler", topics = "${scheduler.start-topic}")
|
|
|
@SneakyThrows
|
|
|
public void cacheProject(ConsumerRecord<String, String> projectRecord) {
|
|
|
- String projectJson = projectRecord.value();
|
|
|
- log.info("ProjectConsumer--cacheManualProject 接收到项目开始消息为:" + projectJson);
|
|
|
+ String initialProjectJson = projectRecord.value();
|
|
|
+ log.info("ProjectConsumer--cacheManualProject 接收到项目开始消息为:" + initialProjectJson);
|
|
|
|
|
|
- ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(projectJson, ProjectMessageDTO.class);
|
|
|
+ ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(initialProjectJson, ProjectMessageDTO.class);
|
|
|
String projectId = projectMessageDTO.getProjectId();
|
|
|
long parallelism = projectMessageDTO.getParallelism();
|
|
|
String projectType = projectMessageDTO.getType();
|
|
@@ -91,11 +88,11 @@ public class ProjectConsumer {
|
|
|
} else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
|
|
|
userId = autoSubProjectMapper.selectCreateUserById(projectId);
|
|
|
} else {
|
|
|
- log.error("ProjectConsumer--cacheManualProject 项目类型错误:" + projectJson);
|
|
|
+ log.error("ProjectConsumer--cacheManualProject 项目类型错误:" + initialProjectJson);
|
|
|
return;
|
|
|
}
|
|
|
if (StringUtil.isEmpty(userId)) {
|
|
|
- log.error("ProjectConsumer--cacheManualProject 未查询到项目创建人:" + projectJson);
|
|
|
+ log.error("ProjectConsumer--cacheManualProject 未查询到项目创建人:" + initialProjectJson);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -107,7 +104,7 @@ public class ProjectConsumer {
|
|
|
if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {
|
|
|
log.info("ProjectConsumer--cacheManualProject 项目 " + projectId + " 的创建人 " + userId + " 为管理员账户或管理员子账户,直接判断服务器能否执行。");
|
|
|
PrefixTO redisPrefix = projectUtil.getRedisPrefixByClusterIdAndProjectId(DictConstants.SYSTEM_CLUSTER_ID, projectId);
|
|
|
- run(DictConstants.SYSTEM_CLUSTER_ID, projectId, projectType, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey(), projectJson, parallelism);
|
|
|
+ run(projectMessageDTO, DictConstants.SYSTEM_CLUSTER_ID, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
|
|
|
return;
|
|
|
} else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) {
|
|
|
clusterPO = clusterMapper.selectByUserId(userId);
|
|
@@ -133,12 +130,12 @@ public class ProjectConsumer {
|
|
|
Set<String> clusterRunningKeySet = stringRedisTemplate.keys(redisPrefix.getClusterRunningPrefix() + "*");
|
|
|
List<String> runningProjectSet;
|
|
|
if (CollectionUtil.isEmpty(clusterRunningKeySet)) {
|
|
|
- run(clusterId, projectId, projectType, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey(), projectJson, parallelism);
|
|
|
+ run(projectMessageDTO, clusterId, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
|
|
|
return;
|
|
|
}
|
|
|
runningProjectSet = projectUtil.getRunningProjectList(clusterRunningKeySet);
|
|
|
if (CollectionUtil.isEmpty(runningProjectSet)) {
|
|
|
- run(clusterId, projectId, projectType, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey(), projectJson, parallelism);
|
|
|
+ run(projectMessageDTO, clusterId, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -150,72 +147,67 @@ public class ProjectConsumer {
|
|
|
}
|
|
|
|
|
|
if (parallelismSum + parallelism <= simulationLicenseNumber) {
|
|
|
- run(clusterId, projectId, projectType, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey(), projectJson, parallelism);
|
|
|
+ run(projectMessageDTO, clusterId, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
|
|
|
} else {
|
|
|
- wait(clusterId, projectId, redisPrefix.getProjectWaitingKey(), projectJson);
|
|
|
+ wait(redisPrefix.getProjectWaitingKey(), projectMessageDTO);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
- * @param clusterId
|
|
|
- * @param projectId
|
|
|
- * @param projectType
|
|
|
- * @param projectRunningKey
|
|
|
- * @param projectJson
|
|
|
- * @param parallelism
|
|
|
- * @return
|
|
|
+ * @param projectMessageDTO 初始接收到的项目启动信息
|
|
|
+ * @param clusterId 集群 id
|
|
|
+ * @param projectRunningKey projectRunningKey
|
|
|
+ * @param projectWaitingKey projectWaitingKey
|
|
|
*/
|
|
|
- public void run(String clusterId, String projectId, String projectType, String projectRunningKey, String projectWaitingKey, String projectJson, long parallelism) {
|
|
|
+ public void run(ProjectMessageDTO projectMessageDTO, String clusterId, String projectRunningKey, String projectWaitingKey) {
|
|
|
|
|
|
-
|
|
|
- KubernetesNodeTO maxParallelismNodeTO = projectUtil.getMaxParallelismNode();
|
|
|
- String maxRestParallelismNode = maxParallelismNodeTO.getName();
|
|
|
- long maxRestParallelism = maxParallelismNodeTO.getMaxParallelism();
|
|
|
- log.info("ProjectConsumer--run 准备在节点 " + maxParallelismNodeTO + " 执行项目 " + projectId + "。");
|
|
|
+ String projectId = projectMessageDTO.getProjectId();
|
|
|
+ int parallelism = projectMessageDTO.getParallelism();
|
|
|
+
|
|
|
+ Map<String, Integer> nodeMap = projectUtil.getNodeMap(parallelism);
|
|
|
+ if (nodeMap.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int parallelismSum = nodeMap.keySet().stream().mapToInt(nodeMap::get).sum();
|
|
|
|
|
|
|
|
|
- if (maxRestParallelism >= parallelism) {
|
|
|
- log.info("ProjectConsumer--run 集群 " + clusterId + " 将项目 " + projectId + "在节点" + maxRestParallelismNode + " 执行!");
|
|
|
- parseProject(projectId, projectType, projectJson, "cluster:" + clusterId, projectRunningKey, maxRestParallelismNode, parallelism);
|
|
|
- } else if (maxRestParallelism > 0L) {
|
|
|
- log.info("ProjectConsumer--run 集群 " + clusterId + " 将项目 " + projectId + "在节点" + maxRestParallelismNode + " 执行!");
|
|
|
- parseProject(projectId, projectType, projectJson, "cluster:" + clusterId, projectRunningKey, maxRestParallelismNode, maxRestParallelism);
|
|
|
+ if (parallelismSum > 0L) {
|
|
|
+ log.info("ProjectConsumer--run 集群 " + clusterId + " 将项目 " + projectId + "在节点 " + nodeMap + " 上以并行度 " + parallelismSum + " 执行!");
|
|
|
+ projectMessageDTO.setCurrentParallelism(parallelismSum);
|
|
|
+ parseProject(nodeMap, projectMessageDTO, "cluster:" + clusterId, projectRunningKey);
|
|
|
} else {
|
|
|
- wait(clusterId, projectId, projectWaitingKey, projectJson);
|
|
|
log.info("ProjectConsumer--cacheManualProject 服务器资源不够,项目 " + projectId + " 暂时加入等待队列。");
|
|
|
+ wait(projectWaitingKey, projectMessageDTO);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
- * @param clusterId
|
|
|
- * @param projectId
|
|
|
- * @param projectWaitingKey
|
|
|
- * @param projectJson
|
|
|
+ * @param projectWaitingKey 项目等待 key
|
|
|
+ * @param projectMessageDTO 项目信息
|
|
|
*/
|
|
|
- public void wait(String clusterId, String projectId, String projectWaitingKey, String projectJson) {
|
|
|
- log.info("ProjectConsumer--wait 集群 " + clusterId + " 将项目 " + projectId + " 放入等待队列!");
|
|
|
- stringRedisTemplate.opsForValue().set(projectWaitingKey, projectJson);
|
|
|
+ @SneakyThrows
|
|
|
+ public void wait(String projectWaitingKey, ProjectMessageDTO projectMessageDTO) {
|
|
|
+ stringRedisTemplate.opsForValue().set(projectWaitingKey, JsonUtil.beanToJson(projectMessageDTO));
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- * @param projectId
|
|
|
- * @param projectJson
|
|
|
- * @param clusterPrefix
|
|
|
- * @param projectRunningPrefix projectRunningKey
|
|
|
- * @param nodeName
|
|
|
- * @param parallelism
|
|
|
+ * @param nodeMap 节点列表以及剩余可用并行度
|
|
|
+ * @param projectMessageDTO 初始接收到的项目启动信息
|
|
|
+ * @param clusterPrefix clusterPrefix
|
|
|
+ * @param projectRunningKey projectRunningKey
|
|
|
*/
|
|
|
@SneakyThrows
|
|
|
- public void parseProject(String projectId, String projectType, String projectJson, String clusterPrefix, String projectRunningPrefix, String nodeName, long parallelism) {
|
|
|
-
|
|
|
- projectService.prepare(clusterPrefix, projectId, projectType, projectRunningPrefix, projectJson, nodeName, parallelism);
|
|
|
- log.info("ProjectConsumer--parseManualProject 接收到项目开始消息为:" + projectJson);
|
|
|
- ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(projectJson, ProjectMessageDTO.class);
|
|
|
+ public void parseProject(Map<String, Integer> nodeMap, ProjectMessageDTO projectMessageDTO, String clusterPrefix, String projectRunningKey) {
|
|
|
+ String projectId = projectMessageDTO.getProjectId();
|
|
|
+ String projectType = projectMessageDTO.getType();
|
|
|
String packageId = projectMessageDTO.getScenePackageId();
|
|
|
- Long maxSimulationTime = projectMessageDTO.getMaxSimulationTime();
|
|
|
+ long videoTime = projectMessageDTO.getMaxSimulationTime();
|
|
|
String vehicleConfigId = projectMessageDTO.getVehicleConfigId();
|
|
|
String algorithmId = projectMessageDTO.getAlgorithmId();
|
|
|
+
|
|
|
+ projectService.prepare(nodeMap, projectMessageDTO, clusterPrefix, projectRunningKey);
|
|
|
String userId = null;
|
|
|
if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
|
|
|
userId = manualProjectMapper.selectCreateUserById(projectId);
|
|
@@ -224,27 +216,26 @@ public class ProjectConsumer {
|
|
|
}
|
|
|
|
|
|
|
|
|
- List<ScenePO> scenePOList = projectService.handlePackage(projectRunningPrefix, projectId, packageId);
|
|
|
+ List<ScenePO> scenePOList = projectService.handlePackage(projectRunningKey, projectId, packageId);
|
|
|
+ int taskTotal = scenePOList.size();
|
|
|
+ projectMessageDTO.setTaskTotal(taskTotal);
|
|
|
+ projectMessageDTO.setTaskCompleted(0);
|
|
|
+
|
|
|
+ stringRedisTemplate.opsForValue().set(projectRunningKey, JsonUtil.beanToJson(projectMessageDTO));
|
|
|
Set<ScenePO> scenePOSet = new HashSet<>(scenePOList);
|
|
|
+
|
|
|
|
|
|
|
|
|
VehiclePO vehiclePO = vehicleMapper.selectByVehicleConfigId(vehicleConfigId);
|
|
|
List<CameraPO> cameraPOList = sensorCameraMapper.selectCameraByVehicleConfigId(vehicleConfigId);
|
|
|
List<OgtPO> ogtPOList = sensorOgtMapper.selectOgtByVehicleId(vehicleConfigId);
|
|
|
|
|
|
- projectService.sendTaskMessage(projectRunningPrefix, userId, projectId, projectType, maxSimulationTime, scenePOSet, vehiclePO, cameraPOList, ogtPOList);
|
|
|
+ projectService.sendTaskMessage(projectRunningKey, userId, projectId, projectType, videoTime, scenePOSet, vehiclePO, cameraPOList, ogtPOList);
|
|
|
|
|
|
String algorithmDockerImage = projectService.handleAlgorithm(projectId, algorithmId);
|
|
|
|
|
|
- projectService.transferAndRunYaml(
|
|
|
- nodeName,
|
|
|
- jobTemplate + "job-template.yaml",
|
|
|
- projectId,
|
|
|
- algorithmDockerImage,
|
|
|
- scenePOList.size(),
|
|
|
- parallelism,
|
|
|
- jobYaml + "project-" + projectId + ".yaml"
|
|
|
- );
|
|
|
+
|
|
|
+ projectService.transferAndRunYaml(projectId, nodeMap, algorithmDockerImage);
|
|
|
|
|
|
}
|
|
|
|