From 86a64f205f976be9de83f050f5bc452fe309d29f Mon Sep 17 00:00:00 2001 From: dc Date: Fri, 20 Jun 2025 15:06:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E9=83=A8=E7=BD=B2+Gpu?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=A2=9E=E5=88=A0=E6=94=B9=E6=9F=A5=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 14 +- ...cationOrchestrationServiceApplication.java | 5 +- .../cache/CacheSyncTask.java | 2 +- .../config/CacheAopConfig.java | 2 +- .../config/RedisConfig.java | 12 +- .../{utils => constant}/ConfigConstants.java | 2 +- .../controller/GpuResourceController.java | 17 +-- .../deploy/entity/DeploymentResource.java | 12 -- .../entity/DeployRequest.java | 87 +++++++++++ .../{deploy => }/entity/DeployResponse.java | 2 +- .../entity/DeploymentResource.java | 15 ++ .../entity/{entity => }/GpuResource.java | 85 +++++++---- .../entity/GpuResourceRepository.java | 79 ++++++++++ .../entity/ModelInfo.java | 102 +++++++++++++ .../enums => enumeration}/ErrorCodeEnum.java | 5 +- .../exception/DeployException.java | 27 ++++ .../exception/EvaluationFailedException.java | 13 ++ .../exception/GpuGlobalException.java | 4 +- .../exception/PermissionDeniedException.java | 2 +- .../mapper/GpuMapper.java | 10 +- .../mapper/GpuResourceDao.java | 2 +- .../{entity/dto => pojo}/GpuCreateDTO.java | 2 +- .../{entity/dto => pojo}/GpuResponseDTO.java | 2 +- .../{entity/dto => pojo}/GpuUpdateDTO.java | 2 +- .../{entity/vo => pojo}/ResponseVO.java | 4 +- .../service/CacheManager.java | 2 +- .../service/GpuManageService.java | 12 +- .../service/GpuResourceService.java | 33 ++++ .../service/GrayDeployService.java | 51 +++++++ .../service/ModelDeployer.java | 97 ++++++++++++ .../service/ModelEvaluator.java | 134 ++++++++++++++++ .../service/ModelRepositoryClient.java | 98 ++++++++++++ .../service/NormalDeployService.java | 118 +++++++++++++++ .../service/RedisCacheService.java | 31 +++- .../ResourceAllocator.java | 56 ++++++- .../service/impl/GpuManageServiceImpl.java | 143 ++++++++++++++---- .../util/TemplateParser.java | 78 ++++++++++ src/main/resources/application.properties | 8 +- .../resources/mapper/GpuResourceMapper.xml | 8 +- 39 files changed, 1242 insertions(+), 136 deletions(-) rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{utils => constant}/ConfigConstants.java (85%) delete mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployRequest.java rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{deploy => }/entity/DeployResponse.java (89%) create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeploymentResource.java rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/{entity => }/GpuResource.java (57%) create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResourceRepository.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/ModelInfo.java rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{entity/enums => enumeration}/ErrorCodeEnum.java (84%) create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/DeployException.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/EvaluationFailedException.java rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{entity/dto => pojo}/GpuCreateDTO.java (91%) rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{entity/dto => pojo}/GpuResponseDTO.java (95%) rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{entity/dto => pojo}/GpuUpdateDTO.java (94%) rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{entity/vo => pojo}/ResponseVO.java (87%) create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuResourceService.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GrayDeployService.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelDeployer.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelEvaluator.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelRepositoryClient.java create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/NormalDeployService.java rename src/main/java/com/bipt/intelligentapplicationorchestrationservice/{deploy/deployment => service}/ResourceAllocator.java (53%) create mode 100644 src/main/java/com/bipt/intelligentapplicationorchestrationservice/util/TemplateParser.java diff --git a/pom.xml b/pom.xml index a143d44..06b845a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ - 21 + 17 2022.0.4 @@ -126,10 +126,6 @@ org.springframework.boot spring-boot-starter-validation - - org.springframework.boot - spring-boot-starter-amqp - org.apache.commons @@ -146,7 +142,15 @@ org.springframework.boot spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-amqp + + + com.baomidou mybatis-plus-generator diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/IntelligentApplicationOrchestrationServiceApplication.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/IntelligentApplicationOrchestrationServiceApplication.java index 5d34a0f..57b84c1 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/IntelligentApplicationOrchestrationServiceApplication.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/IntelligentApplicationOrchestrationServiceApplication.java @@ -2,6 +2,7 @@ package com.bipt.intelligentapplicationorchestrationservice; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; +import org.slf4j.Logger; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -11,9 +12,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @EnableTransactionManagement @EnableDiscoveryClient -@Slf4j +//@Slf4j public class IntelligentApplicationOrchestrationServiceApplication { - + private static final Logger log = org.slf4j.LoggerFactory.getLogger(IntelligentApplicationOrchestrationServiceApplication.class); public static void main(String[] args) { SpringApplication.run(IntelligentApplicationOrchestrationServiceApplication.class, args); log.info("server started"); diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java index 40c2de2..b735444 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/cache/CacheSyncTask.java @@ -2,7 +2,7 @@ package com.bipt.intelligentapplicationorchestrationservice.cache; import com.bipt.intelligentapplicationorchestrationservice.service.CacheManager; import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java index 7a9c410..88080a9 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/CacheAopConfig.java @@ -2,7 +2,7 @@ package com.bipt.intelligentapplicationorchestrationservice.config; import com.bipt.intelligentapplicationorchestrationservice.service.CacheManager; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java index a6de6a1..41d7a34 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/config/RedisConfig.java @@ -15,6 +15,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.web.client.RestTemplate; import java.time.Duration; @@ -35,6 +36,11 @@ public class RedisConfig { @Value("${spring.data.redis.ssl:false}") private boolean useSsl; + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + @Bean public RedisConnectionFactory redisConnectionFactory() { // 1. 创建 SocketOptions @@ -83,12 +89,6 @@ public class RedisConfig { RedisTemplate template = new RedisTemplate<>(); Logger log = (Logger) LoggerFactory.getLogger(RedisConfig.class); log.info("开始创建redis模板对象..."); - //RedisTemplate redisTemplate = new RedisTemplate(); - //设置redis的连接工厂对象 - //redisTemplate.setConnectionFactory(redisConnectionFactory); - //设置redis key的序列化器 - //redisTemplate.setKeySerializer(new StringRedisSerializer()); - //RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/utils/ConfigConstants.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/constant/ConfigConstants.java similarity index 85% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/utils/ConfigConstants.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/constant/ConfigConstants.java index 33cb408..2a0c66b 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/utils/ConfigConstants.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/constant/ConfigConstants.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.utils; +package com.bipt.intelligentapplicationorchestrationservice.constant; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java index 507cde1..f26f167 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/controller/GpuResourceController.java @@ -1,32 +1,26 @@ package com.bipt.intelligentapplicationorchestrationservice.controller; - -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.ResponseVO; import com.bipt.intelligentapplicationorchestrationservice.service.GpuManageService; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; - import java.util.List; - @RestController @RequestMapping public class GpuResourceController { @Autowired private GpuManageService gpuManageService; - @PostMapping public ResponseVO addGpu(@Valid @RequestBody GpuCreateDTO dto){ return gpuManageService.createGpuResource(dto); } - @DeleteMapping("/{gpuId}") public ResponseVO removeGpu(@PathVariable("gpuId") Long gpuId){ return gpuManageService.deleteGpuResource(gpuId); } - @PutMapping("/{gpuId}") public void updateGpuResource( @PathVariable Long gpuId, @@ -34,15 +28,12 @@ public class GpuResourceController { dto.setGPUId(gpuId); gpuManageService.updateGpuResource(dto); } - @GetMapping("/search") public ResponseVO> searchGpuResources( @RequestParam(required = false) String model, @RequestParam(required = false) Integer memorySize, @RequestParam(required = false) String ip){ - List resources = gpuManageService.searchByCriteria(model, memorySize,ip); - return ResponseVO.success(resources); } } diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java deleted file mode 100644 index 08935ef..0000000 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeploymentResource.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.bipt.intelligentapplicationorchestrationservice.deploy.entity; - -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class DeploymentResource { - private final GpuResource gpu; - private final String url; -} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployRequest.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployRequest.java new file mode 100644 index 0000000..7bf9818 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployRequest.java @@ -0,0 +1,87 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity; + +import java.util.Objects; + +public class DeployRequest { + private String modelId; + private int requiredMemory; + private DeployType deployType; + private ModelInfo modelInfo; + + // 部署类型枚举 + public enum DeployType { + NORMAL, + GRAY + } + // 默认构造函数 + public DeployRequest() { + } + + public DeployRequest(String modelId, int requiredMemory, DeployType deployType, ModelInfo modelInfo) { + this.modelId = modelId; + this.requiredMemory = requiredMemory; + this.deployType = deployType; + this.modelInfo = modelInfo; + } + + // Getter & Setter 方法 + public String getModelId() { + return modelId; + } + + public void setModelId(String modelId) { + this.modelId = modelId; + } + + public int getRequiredMemory() { + return requiredMemory; + } + + public void setRequiredMemory(int requiredMemory) { + this.requiredMemory = requiredMemory; + } + + public DeployType getDeployType() { + return deployType; + } + + public void setDeployType(DeployType deployType) { + this.deployType = deployType; + } + + public ModelInfo getModelInfo() { + return modelInfo; + } + + public void setModelInfo(ModelInfo modelInfo) { + this.modelInfo = modelInfo; + } + + // Equals 和 HashCode 方法 + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DeployRequest that = (DeployRequest) o; + return requiredMemory == that.requiredMemory && + Objects.equals(modelId, that.modelId) && + deployType == that.deployType && + Objects.equals(modelInfo, that.modelInfo); + } + + @Override + public int hashCode() { + return Objects.hash(modelId, requiredMemory, deployType, modelInfo); + } + + // toString 方法 + @Override + public String toString() { + return "DeployRequest{" + + "modelId='" + modelId + '\'' + + ", requiredMemory=" + requiredMemory + + ", deployType=" + deployType + + ", modelInfo=" + modelInfo + + '}'; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployResponse.java similarity index 89% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployResponse.java index 28a9481..3190c99 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/entity/DeployResponse.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeployResponse.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.deploy.entity; +package com.bipt.intelligentapplicationorchestrationservice.entity; public class DeployResponse { private boolean isSuccess; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeploymentResource.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeploymentResource.java new file mode 100644 index 0000000..655bb85 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/DeploymentResource.java @@ -0,0 +1,15 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity; + +import lombok.Getter; + +@Getter +//@AllArgsConstructor +public class DeploymentResource { + private final GpuResource gpu; + private final String url; + + public DeploymentResource(GpuResource gpu, String url) { + this.gpu = gpu; + this.url = url; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResource.java similarity index 57% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResource.java index c1e5802..35a50a6 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/entity/GpuResource.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResource.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.entity; +package com.bipt.intelligentapplicationorchestrationservice.entity; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; @@ -18,6 +18,34 @@ public class GpuResource { @TableField("GPUModel") private String GPUModel; + public Integer getGPUMemorySize() { + return GPUMemorySize; + } + + public Long getGPUId() { + return GPUId; + } + + public String getGPUModel() { + return GPUModel; + } + + public String getIp() { + return Ip; + } + + public LocalDateTime getCreateTime() { + return CreateTime; + } + + public LocalDateTime getUpdateTime() { + return UpdateTime; + } + + public Integer getGPUMaxMemory() { + return GPUMaxMemory; + } + @Getter @TableField("GPUMemorySize") private Integer GPUMemorySize; @@ -65,32 +93,33 @@ public class GpuResource { public GpuResource() {} -// public void setGPUId(Long GPUId) { -// this.GPUId = GPUId; -// } -// -// public void setGPUModel(String GPUModel) { -// this.GPUModel = GPUModel; -// } -// -// public void setGPUMemorySize(Integer GPUMemorySize) { -// this.GPUMemorySize = GPUMemorySize; -// } -// -// public void setIsDeleted(Integer isDeleted) { -// this.isDeleted = isDeleted; -// } -// -// public void setIp(String ip) { -// Ip = ip; -// } -// -// public void setCreateTime(LocalDateTime createTime) { -// CreateTime = createTime; -// } -// -// public void setUpdateTime(LocalDateTime updateTime) { -// UpdateTime = updateTime; -// } + public void setGPUId(Long GPUId) { + this.GPUId = GPUId; + } + + public void setGPUModel(String GPUModel) { + this.GPUModel = GPUModel; + } + + public void setGPUMemorySize(Integer GPUMemorySize) { + this.GPUMemorySize = GPUMemorySize; + } + + public void setIsDeleted(Integer isDeleted) { + this.isDeleted = isDeleted; + } + + public void setIp(String ip) { + Ip = ip; + } + + public void setCreateTime(LocalDateTime createTime) { + CreateTime = createTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + UpdateTime = updateTime; + } + } diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResourceRepository.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResourceRepository.java new file mode 100644 index 0000000..7a96926 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/GpuResourceRepository.java @@ -0,0 +1,79 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity; + +import com.bipt.intelligentapplicationorchestrationservice.service.RedisCacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@Repository +public class GpuResourceRepository { + // Redis键定义 + // Redis键模式定义 + private static final String GPU_KEY_PREFIX = "gpu:"; + + private final RedisCacheService redisCacheService; + + @Autowired + public GpuResourceRepository(RedisCacheService redisCacheService) { + this.redisCacheService = redisCacheService; + } + + /** + * 保存或更新GPU资源 + * @param resource GPU资源对象 + */ + public void save(GpuResource resource) { + redisCacheService.put(resource.getGPUId().toString(), resource); + } + + /** + * 按ID查询GPU资源 + * @param id GPU资源ID + * @return GPU资源对象(可能为null) + */ + public GpuResource findById(Long id) { + return redisCacheService.get(id.toString()); + } + + /** + public List findByStatus(Status status) { + // 由于Redis存储结构不支持直接按属性查询,需要通过keys + 过滤方式实现 + // 注意:生产环境中应考虑使用RedisSCAN替代KEYS(此处为简写) + Set keys = redisCacheService.scanKeys(GPU_KEY_PREFIX + "*"); + + List result = new ArrayList<>(); + keys.forEach(key -> { + String gpuId = key.substring(GPU_KEY_PREFIX.length()); + GpuResource resource = redisCacheService.get(gpuId); + if (resource != null && resource.getStatus() == status) { + result.add(resource); + } + }); + + return result; + } + + public void updateStatus(Long gpuId, Status newStatus) { + GpuResource resource = findById(gpuId); + if (resource != null) { + resource.setStatus(newStatus); + save(resource); + } + } + */ + public List findAll() { + Set keys = redisCacheService.scanKeys("gpu:*"); + return keys.stream() + .map(key -> { + String gpuId = key.substring(4); // 去除"gpu:"前缀 + return redisCacheService.get(gpuId); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } +} + diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/ModelInfo.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/ModelInfo.java new file mode 100644 index 0000000..ffe536e --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/ModelInfo.java @@ -0,0 +1,102 @@ +package com.bipt.intelligentapplicationorchestrationservice.entity; + +import java.util.Objects; + +public class ModelInfo { + private String modelId; + private String modelName; + private String modelType; + private String preprocessScript; + private String modelFilePath; + private String storageLocation; + + public String getModelId() { + return modelId; + } + + public void setModelId(String modelId) { + this.modelId = modelId; + } + + // Getter & Setter 方法 + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public String getModelType() { + return modelType; + } + + public void setModelType(String modelType) { + this.modelType = modelType; + } + + public String getPreprocessScript() { + return preprocessScript; + } + + public void setPreprocessScript(String preprocessScript) { + this.preprocessScript = preprocessScript; + } + + public String getModelFilePath() { + return modelFilePath; + } + + public void setModelFilePath(String modelFilePath) { + this.modelFilePath = modelFilePath; + } + + public void setStorageLocation(String storageLocation) { + // 验证路径格式 + if (storageLocation != null && !isValidStoragePath(storageLocation)) { + throw new IllegalArgumentException("无效的存储路径: " + storageLocation); + } + this.storageLocation = storageLocation; + } + + private boolean isValidStoragePath(String path) { + // 1. 基本非空检查 + if (path == null || path.trim().isEmpty()) return false; + + // 2. 防止路径遍历攻击 + if (path.contains("..")) return false; + + // 3. 仅允许合法路径格式 + return path.startsWith("/") || + path.startsWith("s3://") || + path.matches("[a-zA-Z]:\\\\"); // Windows 路径 + } + + // Equals 和 HashCode 方法 + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ModelInfo modelInfo = (ModelInfo) o; + return Objects.equals(modelName, modelInfo.modelName) && + Objects.equals(modelType, modelInfo.modelType) && + Objects.equals(preprocessScript, modelInfo.preprocessScript) && + Objects.equals(modelFilePath, modelInfo.modelFilePath); + } + + @Override + public int hashCode() { + return Objects.hash(modelName, modelType, preprocessScript, modelFilePath); + } + + // toString 方法 + @Override + public String toString() { + return "ModelInfo{" + + "modelName='" + modelName + '\'' + + ", modelType='" + modelType + '\'' + + ", preprocessScript='" + preprocessScript + '\'' + + ", modelFilePath='" + modelFilePath + '\'' + + '}'; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/enumeration/ErrorCodeEnum.java similarity index 84% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/enumeration/ErrorCodeEnum.java index 9f28c98..8de067c 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/enums/ErrorCodeEnum.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/enumeration/ErrorCodeEnum.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.enums; +package com.bipt.intelligentapplicationorchestrationservice.enumeration; import lombok.Getter; @@ -19,7 +19,8 @@ public enum ErrorCodeEnum { DB_CONNECTION_FAILED(701, "数据库连接错误"), VALIDATION_ERROR(801,"参数校验异常" ), - CACHE_INIT_ERROR(901, "缓存初始化失败"); + CACHE_INIT_ERROR(901, "缓存初始化失败"), + INTERNAL_SERVER_ERROR(201,"内部服务出错" ); public int getCode() { return code; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/DeployException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/DeployException.java new file mode 100644 index 0000000..a4b4493 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/DeployException.java @@ -0,0 +1,27 @@ +package com.bipt.intelligentapplicationorchestrationservice.exception; + +public class DeployException extends RuntimeException{ + // 错误代码 + private int errorCode = 500; + + public DeployException(String message) { + super(message); + } + + public DeployException(String message, Throwable cause) { + super(message, cause); + } + + public DeployException(Throwable cause) { + super(cause); + } + + public DeployException(String message, int errorCode) { + super(message); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/EvaluationFailedException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/EvaluationFailedException.java new file mode 100644 index 0000000..bc151c3 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/EvaluationFailedException.java @@ -0,0 +1,13 @@ +package com.bipt.intelligentapplicationorchestrationservice.exception; + +public class EvaluationFailedException extends DeployException{ + public EvaluationFailedException(String message) { + super(message); + } + public EvaluationFailedException(String message, Throwable cause) { + super(message, cause); + } + public EvaluationFailedException() { + super("模型评估未通过,无法部署"); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GpuGlobalException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GpuGlobalException.java index 52d0140..a2c835d 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GpuGlobalException.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/GpuGlobalException.java @@ -1,7 +1,7 @@ package com.bipt.intelligentapplicationorchestrationservice.exception; -import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; -import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.enumeration.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.pojo.ResponseVO; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java index fcb4513..d09e4c0 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/exception/PermissionDeniedException.java @@ -1,6 +1,6 @@ package com.bipt.intelligentapplicationorchestrationservice.exception; -import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.enumeration.ErrorCodeEnum; import lombok.Getter; @Getter diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java index 4f52841..a1ffed8 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuMapper.java @@ -1,13 +1,13 @@ package com.bipt.intelligentapplicationorchestrationservice.mapper; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; import org.mapstruct.Mapper; import org.mapstruct.MappingConstants; -@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel = "spring") public interface GpuMapper { GpuResource toEntity(GpuCreateDTO dto); GpuResource toEntity(GpuUpdateDTO dto); diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java index e415e25..7efab1f 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/mapper/GpuResourceDao.java @@ -1,6 +1,6 @@ package com.bipt.intelligentapplicationorchestrationservice.mapper; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; import org.apache.ibatis.annotations.*; import org.apache.ibatis.jdbc.SQL; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuCreateDTO.java similarity index 91% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuCreateDTO.java index 48b901e..8916ec8 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuCreateDTO.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuCreateDTO.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.dto; +package com.bipt.intelligentapplicationorchestrationservice.pojo; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuResponseDTO.java similarity index 95% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuResponseDTO.java index 66312b4..83dcb0a 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuResponseDTO.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuResponseDTO.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.dto; +package com.bipt.intelligentapplicationorchestrationservice.pojo; import lombok.Data; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuUpdateDTO.java similarity index 94% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuUpdateDTO.java index 3ca1dbc..10263d5 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/dto/GpuUpdateDTO.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/GpuUpdateDTO.java @@ -1,4 +1,4 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.dto; +package com.bipt.intelligentapplicationorchestrationservice.pojo; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/ResponseVO.java similarity index 87% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/ResponseVO.java index e7ab79b..06e356e 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/entity/vo/ResponseVO.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/pojo/ResponseVO.java @@ -1,6 +1,6 @@ -package com.bipt.intelligentapplicationorchestrationservice.entity.vo; +package com.bipt.intelligentapplicationorchestrationservice.pojo; -import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.enumeration.ErrorCodeEnum; import java.io.Serializable; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java index b39d307..2d470b8 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/CacheManager.java @@ -2,7 +2,7 @@ package com.bipt.intelligentapplicationorchestrationservice.service; import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; import com.bipt.intelligentapplicationorchestrationservice.exception.CacheInitException; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java index 870af09..3d53da2 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuManageService.java @@ -1,9 +1,10 @@ package com.bipt.intelligentapplicationorchestrationservice.service; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.ResponseVO; +import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -12,4 +13,7 @@ public interface GpuManageService { public ResponseVO deleteGpuResource(Long gpuId); public void updateGpuResource(GpuUpdateDTO entity); public List searchByCriteria(String model, Integer memorySize, String ip); + + @Transactional + ResponseVO createGpuResourceWithTrace(GpuCreateDTO dto); } diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuResourceService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuResourceService.java new file mode 100644 index 0000000..4f4763f --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GpuResourceService.java @@ -0,0 +1,33 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResourceRepository; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class GpuResourceService { + @Autowired + private GpuResourceRepository repository; + + @Cacheable(value = "availableGpus") + public List getAvailableResources() { +// 获取所有未删除的资源 + return repository.findAll().stream() + .filter(gpu -> gpu.getIsDeleted() == null || !gpu.getIsDeleted()) + .collect(Collectors.toList()); } + + public void markAsAllocated(Long gpuId, int allocatedMemory) { + GpuResource gpu = repository.findById(gpuId); + if (gpu != null) { + // 更新已使用内存 + int currentMemory = gpu.getGPUMemorySize() != null ? gpu.getGPUMemorySize() : 0; + gpu.setGPUMemorySize(currentMemory + allocatedMemory); + repository.save(gpu); + } + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GrayDeployService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GrayDeployService.java new file mode 100644 index 0000000..f9930f3 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/GrayDeployService.java @@ -0,0 +1,51 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployRequest; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployResponse; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeploymentResource; +import com.bipt.intelligentapplicationorchestrationservice.exception.EvaluationFailedException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +@Service +public class GrayDeployService { + @Autowired + private ModelEvaluator modelEvaluator; + + @Autowired + private ResourceAllocator resourceAllocator; + + @Autowired + private GpuResourceService gpuService; + +// @Autowired +// private MQSender mqSender; + + public DeployResponse process(DeployRequest request) { + // 检查评估状态 + if (!modelEvaluator.isEvaluationPassed(request.getModelId())) { + throw new EvaluationFailedException("模型评估未通过"); + } + + // 分配资源并获取URL + DeploymentResource resource = resourceAllocator.allocate( + gpuService.getAvailableResources(), + request.getRequiredMemory(), + request.getModelId(), + true + ); + +// // 发送MQ灰度通知 +// mqSender.sendGrayDeployNotification( +// resource.getUrl(), +// request.getModelId(), +// resource.getGpu().getGPUId() +// ); + // 标记资源已分配(更新内存使用量) + gpuService.markAsAllocated( + resource.getGpu().getGPUId(), + request.getRequiredMemory() + ); + return DeployResponse.success(resource.getUrl()); + + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelDeployer.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelDeployer.java new file mode 100644 index 0000000..a539f6f --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelDeployer.java @@ -0,0 +1,97 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployRequest; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployResponse; +import com.bipt.intelligentapplicationorchestrationservice.entity.ModelInfo; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.exception.DeployException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + + +@Service +public class ModelDeployer { + + @Autowired + private ModelRepositoryClient modelRepositoryClient; + + @Autowired + private ModelEvaluator modelEvaluationService; + + @Autowired + private NormalDeployService normalDeployService; + + @Autowired + private GrayDeployService grayDeployService; + + @Autowired + private ResourceAllocator resourceAllocator; + + @Autowired + private GpuResourceService gpuResourceService; + + public DeployResponse deploy(DeployRequest request) { + try { + // 1. 获取完整模型信息 + ModelInfo modelInfo = getModelInfo(request.getModelId()); + + // 2. 更新请求中的模型信息 + request.setModelInfo(modelInfo); + + // 3. 添加模型评估检查 + if (!isEvaluationPassed(modelInfo)) { + return DeployResponse.fail(403, + "模型[" + modelInfo.getModelName() + "]评估未通过,无法部署"); + } + List availableResources = gpuResourceService.getAvailableResources(); + int requiredMemory = request.getRequiredMemory(); + String modelId = request.getModelId(); + + if (!resourceAllocator.checkResourceQuota(availableResources, requiredMemory, modelId)){ + return DeployResponse.fail(507, "资源配额不足。需要内存: " + requiredMemory + "MB\n"); + } + + // 4. 根据部署类型路由 + if (request.getDeployType() == DeployRequest.DeployType.NORMAL) { + return normalDeployService.process(request); + } else { + return grayDeployService.process(request); + } + } catch (DeployException e) { + return DeployResponse.fail(404, "获取模型信息失败: " + e.getMessage()); + } catch (Exception e) { + return DeployResponse.fail(500, "部署失败: " + e.getMessage()); + } + } + + /** + * 从模型仓库获取模型详细信息 + */ + private ModelInfo getModelInfo(String modelId) { + // 添加缓存和重试机制 + ModelInfo modelInfo = modelRepositoryClient.getModelInfo(modelId); + + // 验证关键字段 + if (modelInfo.getModelFilePath() == null) { + throw new DeployException("模型文件路径未定义"); + } + + // 获取额外信息 + modelInfo.setStorageLocation( + modelRepositoryClient.getModelStorageLocation(modelId) + ); + + return modelInfo; + } + + /** + * 检查模型评估状态 + */ + private boolean isEvaluationPassed(ModelInfo modelInfo) { + return modelEvaluationService.isEvaluationPassed( + modelInfo.getModelId() + ); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelEvaluator.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelEvaluator.java new file mode 100644 index 0000000..248b4e8 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelEvaluator.java @@ -0,0 +1,134 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Component +public class ModelEvaluator { + @Value("${model.evaluation.service-url}") + private String evaluationServiceUrl; + + @Value("${model.evaluation.api-timeout:3000}") + private int apiTimeout; + + @Autowired + private RestTemplate restTemplate; + + /** + * 检查模型评估是否通过 + * @param modelId 模型ID + * @return 评估是否通过 + */ + public boolean isEvaluationPassed(String modelId) { + return isEvaluationPassed(modelId, null); + } + + /** + * 检查模型评估是否通过(带版本号) + * @param modelId 模型ID + * @param version 模型版本 + * @return 评估是否通过 + */ + public boolean isEvaluationPassed(String modelId, String version) { + // 1. 构建API调用参数 + Map params = new HashMap<>(); + params.put("modelId", modelId); + if (version != null) { + params.put("version", version); + } + + try { + // 2. 设置请求头和超时 + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("X-Request-ID", generateRequestId(modelId)); + + // 3. 调用评估API + ResponseEntity response = restTemplate.exchange( + buildEvaluationUrl(modelId, version), + HttpMethod.GET, + new HttpEntity<>(headers), + EvaluationResponse.class + ); + + // 4. 处理响应 + if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { + return response.getBody().isPassed(); + } else if (response.getStatusCode() == HttpStatus.NOT_FOUND) { + logEvaluationWarning(modelId, "模型未找到"); + } else { + logEvaluationError(modelId, "评估服务返回非200状态: " + response.getStatusCode()); + } + } catch (Exception e) { + logEvaluationError(modelId, "评估服务调用失败: " + e.getMessage()); + } + + // 5. 默认返回失败 + return false; + } + + // ================= 辅助方法 ================= + + /** + * 构建评估API URL + */ + private String buildEvaluationUrl(String modelId, String version) { + String baseUrl = evaluationServiceUrl + "/models/" + modelId + "/evaluation"; + return version != null ? baseUrl + "?version=" + version : baseUrl; + } + + /** + * 生成请求ID(用于日志追踪) + */ + private String generateRequestId(String modelId) { + return "eval-" + modelId + "-" + System.currentTimeMillis(); + } + + /** + * 记录评估错误日志 + */ + private void logEvaluationError(String modelId, String message) { + // 实际实现应使用日志框架(如SLF4J) + System.err.println("[" + modelId + "] 评估错误: " + message); + } + + /** + * 记录评估警告日志 + */ + private void logEvaluationWarning(String modelId, String message) { + // 实际实现应使用日志框架 + System.out.println("[" + modelId + "] 评估警告: " + message); + } + + /** + * 评估响应内部类 + */ + private static class EvaluationResponse { + private boolean passed; + private String reason; + private String evaluatedAt; + + // 需要默认构造方法用于JSON反序列化 + public EvaluationResponse() {} + + public boolean isPassed() { + return passed; + } + + public String getReason() { + return reason; + } + + public String getEvaluatedAt() { + return evaluatedAt; + } + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelRepositoryClient.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelRepositoryClient.java new file mode 100644 index 0000000..2a17eb9 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ModelRepositoryClient.java @@ -0,0 +1,98 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.ModelInfo; +import com.bipt.intelligentapplicationorchestrationservice.exception.DeployException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.Collections; + + +@Component +public class ModelRepositoryClient { + + @Value("${model.repository.url}") + private String repositoryBaseUrl; + + @Value("${model.repository.api-key}") + private String apiKey; + + @Autowired + private RestTemplate restTemplate; + + /** + * 从模型仓库获取模型信息 + * + * @param modelId 模型唯一标识 + * @return 完整的模型信息对象 + */ + public ModelInfo getModelInfo(String modelId) { + // 1. 构建请求URL + String url = repositoryBaseUrl + "/models/" + modelId + "/info"; + + // 2. 设置认证头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("X-API-KEY", apiKey); + headers.set("Model-Id", modelId); + + HttpEntity entity = new HttpEntity<>(headers); + + try { + // 3. 发送请求到模型仓库服务 + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + ModelInfo.class + ); + + // 4. 处理响应 + if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { + return response.getBody(); + } else if (response.getStatusCode() == HttpStatus.NOT_FOUND) { + throw new DeployException("模型未找到: " + modelId); + } else { + throw new DeployException("获取模型信息失败,状态码: " + response.getStatusCode()); + } + } catch (Exception e) { + throw new DeployException("访问模型仓库失败: " + e.getMessage(), e); + } + } + public String getModelStorageLocation(String modelId) { + // 1. 构建请求URL + String url = repositoryBaseUrl + "/models/" + modelId + "/storage-location"; + + // 2. 设置认证头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("X-API-KEY", apiKey); + headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN)); + + HttpEntity entity = new HttpEntity<>(headers); + + try { + // 3. 发送请求到模型仓库服务 + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + String.class + ); + + // 4. 处理响应 + if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { + return response.getBody(); + } else if (response.getStatusCode() == HttpStatus.NOT_FOUND) { + throw new DeployException("模型存储位置未找到: " + modelId); + } else { + throw new DeployException("获取存储位置失败,状态码: " + response.getStatusCode()); + } + } catch (Exception e) { + throw new DeployException("访问模型仓库失败: " + e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/NormalDeployService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/NormalDeployService.java new file mode 100644 index 0000000..6893b11 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/NormalDeployService.java @@ -0,0 +1,118 @@ +package com.bipt.intelligentapplicationorchestrationservice.service; + +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployRequest; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeployResponse; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeploymentResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.ModelInfo; +import com.bipt.intelligentapplicationorchestrationservice.exception.EvaluationFailedException; +import com.bipt.intelligentapplicationorchestrationservice.util.TemplateParser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Set; +import java.util.concurrent.TimeUnit; +@Service +public class NormalDeployService { + @Autowired + private ModelEvaluator modelEvaluator; + + @Autowired + private ResourceAllocator resourceAllocator; + + @Autowired + private GpuResourceService gpuService; + + @Autowired + private TemplateParser templateParser; // 使用模板解析器 + + @Value("${model.deploy.script-directory:/opt/deploy_scripts}") + private String scriptDirectory; + + @Value("${model.deploy.script-timeout:300}") + private int scriptTimeout; + + public DeployResponse process(DeployRequest request) { + try { + // 1. 检查模型评估状态(使用ModelInfo包含的模型ID) + ModelInfo modelInfo = request.getModelInfo(); + if (!modelEvaluator.isEvaluationPassed(modelInfo != null ? modelInfo.getModelName() : "")) { + throw new EvaluationFailedException("模型评估未通过"); + } + + // 2. 分配资源并获取URL + DeploymentResource resource = resourceAllocator.allocate( + gpuService.getAvailableResources(), + request.getRequiredMemory(), + modelInfo != null ? modelInfo.getModelName() : "unknown", + false + ); + + // 3. 使用ModelInfo生成部署脚本内容 + String scriptContent = templateParser.generateDeploymentScript( + request.getModelInfo(), + resource.getUrl() + ); + + // 4. 执行部署脚本 + executeDeploymentScript(scriptContent); + + // 5. 标记资源已分配 + gpuService.markAsAllocated( + resource.getGpu().getGPUId(), + request.getRequiredMemory() + ); + + return DeployResponse.success(resource.getUrl()); + + } catch (EvaluationFailedException e) { + return DeployResponse.fail(403, e.getMessage()); + } catch (Exception e) { + return DeployResponse.fail(500, "部署失败: " + e.getMessage()); + } + } + + /** + * 执行部署脚本 + */ + private void executeDeploymentScript(String scriptContent) throws Exception { + // 创建脚本文件 + Path scriptPath = Paths.get(scriptDirectory, "deploy_" + System.currentTimeMillis() + ".sh"); + Files.write(scriptPath, scriptContent.getBytes()); + + // 设置执行权限 (754) + Set permissions = Set.of( + PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE, + PosixFilePermission.OWNER_EXECUTE, + PosixFilePermission.GROUP_READ, + PosixFilePermission.GROUP_EXECUTE, + PosixFilePermission.OTHERS_READ + ); + Files.setPosixFilePermissions(scriptPath, permissions); + + // 执行脚本 + Process process = new ProcessBuilder(scriptPath.toString()) + .directory(Paths.get(scriptDirectory).toFile()) + .start(); + + // 带超时等待 + boolean completed = process.waitFor(scriptTimeout, TimeUnit.SECONDS); + if (!completed) { + process.destroyForcibly(); + throw new RuntimeException("脚本执行超时(限制: " + scriptTimeout + "秒)"); + } + + // 检查退出码 + if (process.exitValue() != 0) { + throw new RuntimeException("脚本执行失败,退出码: " + process.exitValue()); + } + + // 清理脚本文件 + Files.deleteIfExists(scriptPath); + } +} diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java index 7661d6d..c9a006c 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/RedisCacheService.java @@ -1,16 +1,19 @@ package com.bipt.intelligentapplicationorchestrationservice.service; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; +import org.apache.ibatis.cache.CacheException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.concurrent.TimeUnit; @Service @@ -124,4 +127,26 @@ public class RedisCacheService { return false; } } + public Set scanKeys(String pattern) { + try (RedisConnection connection = Objects.requireNonNull( + redisTemplate.getConnectionFactory()).getConnection()) { + + ScanOptions options = ScanOptions.scanOptions() + .match(pattern) + .count(100) // 批量扫描数量 + .build(); + + Set keys = new HashSet<>(); + Cursor cursor = connection.scan(options); + + while (cursor.hasNext()) { + keys.add(new String(cursor.next(), StandardCharsets.UTF_8)); + } + + return keys; + } catch (Exception e) { + throw new CacheException("Keys scan failed", e); + } + } + } \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ResourceAllocator.java similarity index 53% rename from src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java rename to src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ResourceAllocator.java index ec05ce7..9926d77 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/deploy/deployment/ResourceAllocator.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/ResourceAllocator.java @@ -1,8 +1,8 @@ -package com.bipt.intelligentapplicationorchestrationservice.deploy.deployment; +package com.bipt.intelligentapplicationorchestrationservice.service; -import com.bipt.intelligentapplicationorchestrationservice.deploy.entity.DeploymentResource; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; -import com.bipt.intelligentapplicationorchestrationservice.utils.ConfigConstants; +import com.bipt.intelligentapplicationorchestrationservice.entity.DeploymentResource; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.constant.ConfigConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.client.ResourceAccessException; @@ -16,6 +16,54 @@ public class ResourceAllocator { @Autowired private ConfigConstants config; + // 检查资源配额 + public boolean checkResourceQuota(List resources, int requiredMemory, String modelId) { + // 1. 检查全局资源是否充足 + long totalFreeMemory = resources.stream() + .mapToInt(this::getRemainingMemory) + .sum(); + + // 全局内存不足 + if (totalFreeMemory < requiredMemory) { + return false; + } + + // 2. 检查单个GPU是否能满足需求 + boolean canAllocate = resources.stream() + .anyMatch(gpu -> getRemainingMemory(gpu) >= requiredMemory); + + if (!canAllocate) { + // 检查碎片化分配 + return checkFragmentationAllocation(resources, requiredMemory); + } + + return true; + } + + // 检查碎片化分配可能性 + private boolean checkFragmentationAllocation(List resources, int requiredMemory) { + // 按碎片率排序(碎片小的优先) + resources.sort(Comparator.comparingDouble( + r -> (double)getRemainingMemory(r) / r.getGPUMaxMemory() + )); + + // 检查碎片整合后是否可能满足需求 + int accumulatedMemory = 0; + for (GpuResource gpu : resources) { + int fragment = getRemainingMemory(gpu); + // 如果单个碎片就足够,直接返回成功 + if (fragment >= requiredMemory) return true; + + // 累积碎片 + accumulatedMemory += fragment; + if (accumulatedMemory >= requiredMemory) { + return true; + } + } + + return false; + } + //获取剩余内存 private int getRemainingMemory(GpuResource resource){ return resource.getGPUMaxMemory()-resource.getGPUMemorySize(); diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java index 3316e49..6089c89 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/impl/GpuManageServiceImpl.java @@ -1,14 +1,16 @@ -package com.bipt.intelligentapplicationorchestrationservice.service.Impl; +package com.bipt.intelligentapplicationorchestrationservice.service.impl; import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuResourceDao; import com.bipt.intelligentapplicationorchestrationservice.mapper.GpuMapper; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuCreateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuResponseDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.dto.GpuUpdateDTO; -import com.bipt.intelligentapplicationorchestrationservice.entity.entity.GpuResource; -import com.bipt.intelligentapplicationorchestrationservice.entity.enums.ErrorCodeEnum; -import com.bipt.intelligentapplicationorchestrationservice.entity.vo.ResponseVO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuCreateDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuResponseDTO; +import com.bipt.intelligentapplicationorchestrationservice.pojo.GpuUpdateDTO; +import com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource; +import com.bipt.intelligentapplicationorchestrationservice.enumeration.ErrorCodeEnum; +import com.bipt.intelligentapplicationorchestrationservice.pojo.ResponseVO; import com.bipt.intelligentapplicationorchestrationservice.service.GpuManageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,53 +22,128 @@ import java.util.stream.Collectors; @Service public class GpuManageServiceImpl implements GpuManageService { + private static final Logger logger = LoggerFactory.getLogger(GpuManageServiceImpl.class); + @Autowired private GpuResourceDao gpuDao; @Autowired private GpuMapper gpuMapper; - @Autowired - private GpuResourceDao gpuResourceDao; @Transactional - //创建GPU资源 + @Override public ResponseVO createGpuResource(GpuCreateDTO dto) { - GpuResource entity = gpuMapper.toEntity(dto); - gpuDao.insert(entity); - return ResponseVO.success(entity); - } + try { + logger.info("创建GPU资源请求: {}", dto); - @Transactional - //删除GPU资源(逻辑删除) - public ResponseVO deleteGpuResource(Long gpuId) { - GpuResource entity = gpuDao.selectById(gpuId); - if (entity == null) { - return ResponseVO.error(ErrorCodeEnum.GPU_NOT_FOUND); + GpuResource entity = gpuMapper.toEntity(dto); + gpuDao.insert(entity); + + logger.info("创建GPU资源成功, ID: {}", entity.getGPUId()); + return ResponseVO.success(entity); + + } catch (Exception e) { + logger.error("创建GPU资源失败: {}, 参数: {}", e.getMessage(), dto, e); + return ResponseVO.error(ErrorCodeEnum.INTERNAL_SERVER_ERROR); } - gpuDao.isDeleted(gpuId); - return ResponseVO.success(); } @Transactional - //更新GPU资源 + @Override + public ResponseVO deleteGpuResource(Long gpuId) { + logger.info("删除GPU资源请求, ID: {}", gpuId); + + try { + GpuResource entity = gpuDao.selectById(gpuId); + if (entity == null) { + logger.warn("GPU资源不存在, ID: {}", gpuId); + return ResponseVO.error(ErrorCodeEnum.GPU_NOT_FOUND); + } + + gpuDao.isDeleted(gpuId); + logger.info("逻辑删除GPU资源成功, ID: {}", gpuId); + return ResponseVO.success(); + + } catch (Exception e) { + logger.error("删除GPU资源失败, ID: {}, 错误: {}", gpuId, e.getMessage(), e); + return ResponseVO.error(ErrorCodeEnum.INTERNAL_SERVER_ERROR); + } + } + + @Transactional + @Override public void updateGpuResource(GpuUpdateDTO dto) { - GpuResource entity = gpuMapper.toEntity(dto); - gpuDao.updateById(entity); + logger.info("更新GPU资源请求: {}", dto); + + try { + GpuResource entity = gpuMapper.toEntity(dto); + gpuDao.updateById(entity); + logger.info("更新GPU资源成功, ID: {}", entity.getGPUId()); + + } catch (Exception e) { + logger.error("更新GPU资源失败: {}, 参数: {}", e.getMessage(), dto, e); + throw new RuntimeException("更新GPU资源失败", e); + } } @Override - //模糊匹配查询 public List searchByCriteria(String model, Integer memorySize, String ip) { - // PermissionCheckUtil.checkTenantAccess(); - Map params = new HashMap<>(); - if(model != null) params.put("model","%" + model + "%"); - if(memorySize!=null) params.put("memorySize", memorySize); - if(ip!=null) params.put("ip", ip); + if(model != null) params.put("model", "%" + model + "%"); + if(memorySize != null) params.put("memorySize", memorySize); + if(ip != null) params.put("ip", ip); - List entities = gpuResourceDao.selectByFields(params); + logger.info("查询GPU资源条件: {}", params); - return entities.stream().map(gpuMapper::toDTO).collect(Collectors.toList()); + try { + List entities = gpuDao.selectByFields(params); + logger.info("查询到 {} 条GPU资源", entities.size()); + return entities.stream() + .map(gpuMapper::toDTO) + .collect(Collectors.toList()); + + } catch (Exception e) { + logger.error("查询GPU资源失败, 条件: {}, 错误: {}", params, e.getMessage(), e); + throw new RuntimeException("查询GPU资源失败", e); + } + } + + // ========== 新增的日志追踪方法 ========== + + private void logOperation(String methodName, Object... details) { + if (logger.isDebugEnabled()) { + StringBuilder logBuilder = new StringBuilder(methodName); + for (Object detail : details) { + logBuilder.append(" | ").append(detail); + } + logger.debug(logBuilder.toString()); + } + } + + private void logDuration(String methodName, long startTime, boolean success) { + long duration = System.currentTimeMillis() - startTime; + String status = success ? "成功" : "失败"; + logger.info("方法 {} 执行{} | 耗时: {}ms", methodName, status, duration); + } + + // ========== 增强的日志版本 ========== + + @Transactional + @Override + public ResponseVO createGpuResourceWithTrace(GpuCreateDTO dto) { + long start = System.currentTimeMillis(); + try { + logOperation("createGpuResource", "请求参数", dto); + + ResponseVO result = createGpuResource(dto); + + logDuration("createGpuResource", start, true); + return result; + + } catch (Exception e) { + logDuration("createGpuResource", start, false); + throw e; + } } } diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/util/TemplateParser.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/util/TemplateParser.java new file mode 100644 index 0000000..3a417d4 --- /dev/null +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/util/TemplateParser.java @@ -0,0 +1,78 @@ +package com.bipt.intelligentapplicationorchestrationservice.util; + +import com.bipt.intelligentapplicationorchestrationservice.entity.ModelInfo; +import org.springframework.stereotype.Service; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +@Service +public class TemplateParser { + // 使用静态模板避免硬编码(可根据需要扩展为读取外部配置文件) + private static final Map DEPLOYMENT_TEMPLATES = new HashMap<>() {{ + put("tensorflow", "#!/bin/bash\n" + + "# TensorFlow Serving Deployment\n" + + "docker run -d --name {0}-service \\\n" + + " -p {1} \\\n" + + " -v {2}:/models/{0} \\\n" + + " -e MODEL_NAME={0} \\\n" + + " tensorflow/serving:latest\n" + + "# Preprocessing\n" + + "{3} $1"); + + put("pytorch", "#!/bin/bash\n" + + "# TorchServe Deployment\n" + + "torch-model-archiver --model-name {0} \\\n" + + " --version 1.0 \\\n" + + " --serialized-file {2} \\\n" + + " --handler {3} \\\n" + + " --export-path model_store\n" + + "torchserve --start \\\n" + + " --model-store model_store \\\n" + + " --models {0}.mar \\\n" + + " --ncs \\\n" + + " --ts-config config.properties"); + }}; + + public String generateDeploymentScript(ModelInfo modelInfo, String endpointUrl) { + // 提取URL端口号 (假设URL格式为 http://host:port) + String port = extractPortFromUrl(endpointUrl); + + // 获取基础模板 + String template = DEPLOYMENT_TEMPLATES.getOrDefault( + modelInfo.getModelType().toLowerCase(), + getDefaultTemplate() + ); + + // 安全处理空值 + String safeModelName = modelInfo.getModelName() != null ? modelInfo.getModelName() : "unnamed"; + String safeFilePath = modelInfo.getModelFilePath() != null ? modelInfo.getModelFilePath() : ""; + String safeScript = modelInfo.getPreprocessScript() != null ? modelInfo.getPreprocessScript() : "echo 'No preprocessing'"; + + // 填充模板参数 + return MessageFormat.format(template, + safeModelName, + port, + safeFilePath, + safeScript + ); + } + private String extractPortFromUrl(String url) { + if (url == null) return "8080"; // 默认端口 + try { + return url.split(":")[2].replaceAll("[^0-9]", ""); + } catch (Exception e) { + return "8080"; + } + } + + private String getDefaultTemplate() { + return "#!/bin/bash\n" + + "# Universal Deployment Template\n" + + "echo \"Deploying model: {0} at endpoint {1}\"\n" + + "echo \"Model path: {2}\"\n" + + "echo \"Running preprocessing: {3}\"\n" + + "# Add custom deployment logic here"; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8956e4d..c501161 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -32,9 +32,15 @@ spring.cloud.gateway.routes[0].uri=lb://intelligent-application-orchestration-se spring.cloud.gateway.routes[0].predicates[0]=Path=/request - logging.level.org.springframework.web=DEBUG +# ???????? +model.evaluation.service-url=http://evaluation-service:8080/api/v1 +model.evaluation.api-timeout=3000 +# ???????? +model.repository.url=https://model-repo.example.com/api/v1 +model.repository.api-key=SECURE_API_KEY_12345 +model.repository.timeout=5000 #SQL ???????? logging.level.com.bipt.intelligentapplicationorchestrationservice.mapper=DEBUG diff --git a/src/main/resources/mapper/GpuResourceMapper.xml b/src/main/resources/mapper/GpuResourceMapper.xml index 7950d7f..ec4db54 100644 --- a/src/main/resources/mapper/GpuResourceMapper.xml +++ b/src/main/resources/mapper/GpuResourceMapper.xml @@ -5,7 +5,7 @@ + resultType="com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource"> SELECT * FROM gpu_resource WHERE is_deleted = 0 @@ -38,7 +38,7 @@ + resultType="com.bipt.intelligentapplicationorchestrationservice.entity.GpuResource"> SELECT * FROM gpu_resource WHERE GPUId = #{gpuId}