GPU模块设计

This commit is contained in:
dc
2025-05-14 21:38:41 +08:00
parent 736590b3fa
commit 6943f38d1b
22 changed files with 501 additions and 1 deletions

48
pom.xml
View File

@ -27,7 +27,7 @@
<url/> <url/>
</scm> </scm>
<properties> <properties>
<java.version>24</java.version> <java.version>17</java.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -54,6 +54,39 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version> <!-- 确保版本 ≥1.2.0 -->
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -82,6 +115,19 @@
</excludes> </excludes>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -0,0 +1,5 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.config;
public class DataSourceConfig {
}

View File

@ -0,0 +1,4 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.config;
public class MQConfig {
}

View File

@ -0,0 +1,15 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.controller;
import com.bipt.intelligentapplicationorchestrationservice.gpu.service.GpuManageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping
public class GpuResourceController {
@Autowired
private GpuManageService gpuManageService;
}

View File

@ -0,0 +1,19 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.dao;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.entity.GpuResource;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface GpuResourceDao {
@Insert("INSERT INTO gpu_resource (GPUModel, GPUMemorySize, Ip)"+
"VALUES (#{model}, #{memory}, #{ip})")
@Options(useGeneratedKeys = true, keyProperty = "GPUId")
Integer insert(GpuResource entity);
@Select("SELECT * FROM Ipz.public.gpu_resource WHERE GPUId = #{gpuId}")
GpuResource selectById(Long gpuId);
}

View File

@ -0,0 +1,31 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.event;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.time.Clock;
@Getter
@Setter
public class CacheUpdateEvent extends ApplicationEvent {
private final String eventType;
private final Long resourceId;
private final Long timestamp;
// 基础构造函数
public CacheUpdateEvent(Object source, String eventType, Long resourceId) {
super(source); // 必须调用父类构造方法
this.eventType = eventType;
this.resourceId = resourceId;
this.timestamp = System.currentTimeMillis();
}
public CacheUpdateEvent(Object source, String eventType, Long resourceId, Clock clock) {
super(source);
this.eventType = eventType;
this.resourceId = resourceId;
this.timestamp = clock.millis(); // 允许外部控制时间戳
}
}

View File

@ -0,0 +1,26 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.exception;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.enums.ErrorCodeEnum;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.vo.ResponseVO;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(DataAccessResourceFailureException.class)
public ResponseVO handleDBConnectionError() {
return ResponseVO.error(ErrorCodeEnum.DB_CONNECTION_FAILED);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseVO handleValidationError(MethodArgumentNotValidException e) {
return ResponseVO.error(ErrorCodeEnum.VALIDATION_ERROR);
}
@ExceptionHandler(PermissionDeniedException.class)
public ResponseVO handlePermissionDenied(PermissionDeniedException ex) {
return ResponseVO.error(ex.getCode(), ex.getMessage());
}
}

View File

@ -0,0 +1,23 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.exception;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.enums.ErrorCodeEnum;
import lombok.Getter;
@Getter
public class PermissionDeniedException extends RuntimeException {
private final Integer code;
private final String message;
public PermissionDeniedException(ErrorCodeEnum errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public PermissionDeniedException(ErrorCodeEnum errorCode, String appendMessage) {
super(errorCode.getMessage()+": "+appendMessage);
this.code = errorCode.getCode();
this.message = errorCode.getMessage()+": "+appendMessage;
}
}

View File

@ -0,0 +1,14 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.mapper;
import ch.qos.logback.core.model.ComponentModel;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto.GpuCreateDTO;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto.GpuResponseDTO;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.entity.GpuResource;
import org.apache.ibatis.annotations.Mapper;
import org.mapstruct.MappingConstants;
@Mapper
public interface GpuMapper {
GpuResource toEntity(GpuCreateDTO dto);
GpuResponseDTO toResponseDTO(GpuResource entity);
}

View File

@ -0,0 +1,27 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
public class GpuCreateDTO {
@NotBlank(message = "GPU型号不能为空")
@Pattern(regexp = "^([A-Z][A-Z0-9-]+)-\\w+",
message = "型号格式应为 [厂商(大写字母开头)]-[型号],如 Intel-Xe_GPU")
private String GPUModel;
@NotNull(message = "显存容量不能为空")
private Integer GPUMemorySize;
@NotBlank(message = "IP地址不能为空")
@Pattern(regexp = "^\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}$",
message = "IP地址格式无效")
private String Ip;
}

View File

@ -0,0 +1,18 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class GpuResponseDTO {
private Long id;
private String GPUModel;
private Integer GPUMemorySize;
private String Ip;
private LocalDateTime createTime;
public String getCreateTimeStr(){
return "GPU创建时间" + createTime.toString();
}
}

View File

@ -0,0 +1,25 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.*;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class GpuUpdateDTO {
@NotNull(message = "GPU ID cannot be null")
private Long GPUId;
@Pattern(regexp = "^([A-Z][A-Z0-9-]+)-\\w+",
message = "型号格式应为 [厂商(大写字母开头)]-[型号],如 Intel-Xe_GPU")
private String GPUModel;
private Integer GPUMemorySize;
@Pattern(regexp = "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$",
message = "IP地址格式无效")
private String Ip;
}

View File

@ -0,0 +1,43 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import jakarta.validation.constraints.Pattern;
import java.util.Date;
@Setter
@Getter
@Entity
@Table(name = "Gpu_Resource")
public class GpuResource {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long GPUId;
@Column(nullable = false, length = 64)
private String GPUModel;
@Column(nullable = false)
private Integer GPUMemorySize;
@Column(nullable = false, length = 15)
@Pattern(regexp = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$")
private String Ip;
@Column(updatable = false)
@CreationTimestamp
private Date CreateTime;
public GpuResource(Long Id, String Model, Integer MemorySize, String ip, Date create_time) {
this.GPUId = Id;
this.GPUModel = Model;
this.GPUMemorySize = MemorySize;
this.Ip = ip;
this.CreateTime = create_time;
}
}

View File

@ -0,0 +1,36 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.enums;
import lombok.Getter;
import org.hibernate.dialect.aggregate.DB2AggregateSupport;
@Getter
public enum ErrorCodeEnum {
SUCCESS(200, "操作成功"),
SYSTEM_ERROR(500, "系统错误"),
PARAM_INVALID(400, "参数无效"),
PARAM_MISSING(401, "缺少参数"),
IP_FORMAT_ERROR(402, "IP地址格式错误"),
GPU_MODEL_ERROR(403, "GPU型号格式应为[厂商]-[型号]"),
PERMISSION_DENIED(501, "无操作权限"),
GPU_NOT_FOUND(601, "GPU资源不存在"),
DB_CONNECTION_FAILED(701, "数据库连接错误"),
VALIDATION_ERROR(801,"参数校验异常" );
private final int code;
private final String message;
ErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public String toString() {
return "ErrorCodeEnum{" +
"code=" + code +
", message='" + message + '\''+
'}';
}
}

View File

@ -0,0 +1,38 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.model.vo;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.enums.ErrorCodeEnum;
import jakarta.validation.constraints.Null;
import java.io.Serializable;
public class ResponseVO<T> implements Serializable {
private Integer code; //状态码
private String message; //描述信息
private T data; //业务数据
//私有构造方法
private ResponseVO(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
//静态工厂方法
//成功响应(无数据)
public static <T> ResponseVO<T> success() {
return new ResponseVO<>(200, "OK", null);
}
//成功响应(有数据)
public static <T> ResponseVO<T> success(T data) {
return new ResponseVO<>(200, "OK", data);
}
//失败响应(自定义错误码和消息)
public static <T> ResponseVO<T> error(Integer code, String message) {
return new ResponseVO<>(code, message, null);
}
//失败响应(基于预定义错误枚举)
public static <T> ResponseVO<T> error(ErrorCodeEnum errorCode) {
return new ResponseVO<>(errorCode.getCode(), errorCode.getMessage(), null);
}
}

View File

@ -0,0 +1,4 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.mq.listener;
public class ResourceSyncListener {
}

View File

@ -0,0 +1,31 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.mq.producer;
import com.bipt.intelligentapplicationorchestrationservice.gpu.event.CacheUpdateEvent;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class CacheUpdateProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendCacheUpdateMessage(String eventType, Long gpuId) {
CacheUpdateEvent event = new CacheUpdateEvent(this, eventType, gpuId);
MessagePostProcessor processor = message -> {
MessageProperties props = message.getMessageProperties();
props.setMessageId(UUID.randomUUID().toString());
props.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
props.setExpiration("60000"); // 60秒TTL
return message;
};
rabbitTemplate.convertAndSend("GPU_CACHE_QUEUE", event, processor);
}
}

View File

@ -0,0 +1,8 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.service;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto.GpuCreateDTO;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.vo.ResponseVO;
public interface GpuManageService {
public ResponseVO createGpuResource(GpuCreateDTO dto);
}

View File

@ -0,0 +1,31 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.service.impl;
import com.bipt.intelligentapplicationorchestrationservice.gpu.dao.GpuResourceDao;
import com.bipt.intelligentapplicationorchestrationservice.gpu.mapper.GpuMapper;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.dto.GpuCreateDTO;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.entity.GpuResource;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.vo.ResponseVO;
import com.bipt.intelligentapplicationorchestrationservice.gpu.mq.producer.CacheUpdateProducer;
import com.bipt.intelligentapplicationorchestrationservice.gpu.service.GpuManageService;
import com.bipt.intelligentapplicationorchestrationservice.gpu.utils.ValidatorUtil;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GpuManageServiceImpl implements GpuManageService {
@Autowired
private GpuResourceDao gpuDao;
@Autowired
private CacheUpdateProducer mqProducer;
@Autowired
private GpuMapper gpuMapper;
@Transactional
public ResponseVO createGpuResource(GpuCreateDTO dto) {
GpuResource entity = gpuMapper.toEntity(dto);
gpuDao.insert(entity);
return ResponseVO.success(entity);
}
}

View File

@ -0,0 +1,20 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.utils;
import com.bipt.intelligentapplicationorchestrationservice.gpu.exception.PermissionDeniedException;
import com.bipt.intelligentapplicationorchestrationservice.gpu.model.enums.ErrorCodeEnum;
import org.springframework.dao.PermissionDeniedDataAccessException;
import org.springframework.stereotype.Component;
@Component
public class PermissionCheckUtil {
public boolean hasGpuManagePermission(String userId) {
// 这里可以根据用户ID查询数据库或其他方式来判断用户是否有GPU管理权限
// 这里只是一个示例,实际应用中需要根据具体情况进行实现
if("admin".equals(userId)){
return true;
}
else {
throw new PermissionDeniedException(ErrorCodeEnum.PERMISSION_DENIED, "用户" + userId + "无GPU管理权限");
}
}
}

View File

@ -0,0 +1,27 @@
package com.bipt.intelligentapplicationorchestrationservice.gpu.utils;
import org.apache.commons.lang3.StringUtils;
import java.security.InvalidParameterException;
import java.util.regex.Pattern;
public final class ValidatorUtil {
private static final Pattern IP_PATTERN = Pattern.compile("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$");
private static final Pattern MODEL_PATTERN = Pattern.compile("^([A-Z][A-Z0-9-]+)-\\w+");
private ValidatorUtil(){}
public static void validateGpuModel(String model){
if(StringUtils.isBlank(model)||!MODEL_PATTERN.matcher(model).matches()){
throw new InvalidParameterException("GPU型号格式应为[厂商]-[型号]如NVIDIA-A100");
}
}
public static void validateIp(String ip){
if(StringUtils.isBlank(ip)||!IP_PATTERN.matcher(ip).matches()){
throw new InvalidParameterException();
}
}
}

View File

@ -1 +1,10 @@
spring.application.name=intelligent-application-orchestration-service spring.application.name=intelligent-application-orchestration-service
# ?????
spring.datasource.url=jdbc:kingbase8://116.205.121.200:54321/Ipz
spring.datasource.username=system
spring.datasource.password=root
spring.datasource.driver-class-name=com.kingbase8.Driver
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000