From 21910d72d91793eec24997aceb6098d747e068e4 Mon Sep 17 00:00:00 2001 From: educoder Date: Thu, 21 Jul 2022 10:40:34 +0800 Subject: [PATCH] port add --- .../imitate/common/enums/ErrorCodeEnum.java | 3 +- .../game/controller/VscodeController.java | 10 +++ .../web/module/game/service/ProxyService.java | 75 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 web/src/main/java/com/imitate/web/module/game/service/ProxyService.java diff --git a/common/src/main/java/com/imitate/common/enums/ErrorCodeEnum.java b/common/src/main/java/com/imitate/common/enums/ErrorCodeEnum.java index e10db0e..fb2cfa3 100644 --- a/common/src/main/java/com/imitate/common/enums/ErrorCodeEnum.java +++ b/common/src/main/java/com/imitate/common/enums/ErrorCodeEnum.java @@ -22,7 +22,8 @@ public enum ErrorCodeEnum { AFTERMATH_EXP("000013","评测线程出错,善后处理发生异常"), GIT_FAIL("000014","获取git凭证失败: "), GIT_CREDENTIAL_FAIL("000015","设置git凭证失败:"), - + NOT_CHECK_SVS("000016","未检测到服务启动,请先启动服务"), + SVC_PORT_MAX ("000017","预览服务端口达到上限"), CLONE_FAIL("100001","克隆失败"), EVALUATION_SHELL_FAIL("100002","生成评测脚本失败"), diff --git a/web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java b/web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java index 3513cef..4ddb7bb 100644 --- a/web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java +++ b/web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java @@ -1,6 +1,7 @@ package com.imitate.web.module.game.controller; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.map.MapUtil; import com.alibaba.fastjson.JSONObject; import com.imitate.common.annotation.PublicUrl; import com.imitate.common.bean.ApiResult; @@ -18,6 +19,7 @@ import com.imitate.common.util.ThreadUtils; import com.imitate.common.util.TpUtils; import com.imitate.web.module.game.service.GameService; import com.imitate.web.module.game.service.GitService; +import com.imitate.web.module.game.service.ProxyService; import com.imitate.web.module.game.service.VscodeService; import com.imitate.web.module.game.thread.code.LocalCheckJob; import com.imitate.web.params.GetVsCodeParam; @@ -67,6 +69,9 @@ public class VscodeController { @Autowired private RunPodService runPodService; + @Autowired + private ProxyService proxyService; + @Qualifier("gitTaskExecutor") @@ -196,6 +201,11 @@ public class VscodeController { + @RequestMapping(path = "/getPort",method = RequestMethod.POST) + public R getPort(@RequestParam String tpiID, @RequestParam Integer type, @RequestParam Integer port) { + int proxyPort = proxyService.getContainerExternalMappingPort(tpiID, type, port); + return R.ok().setData(MapUtil.builder("port", proxyPort).build()); + } diff --git a/web/src/main/java/com/imitate/web/module/game/service/ProxyService.java b/web/src/main/java/com/imitate/web/module/game/service/ProxyService.java new file mode 100644 index 0000000..3ac0c78 --- /dev/null +++ b/web/src/main/java/com/imitate/web/module/game/service/ProxyService.java @@ -0,0 +1,75 @@ +package com.imitate.web.module.game.service; + + +import com.imitate.common.enums.ErrorCodeEnum; +import com.imitate.common.exception.BusinessException; +import com.imitate.common.k8s.service.K8sService; +import com.imitate.common.k8s.service.PortService; +import com.imitate.common.k8s.service.RunPodService; +import com.imitate.common.k8s.util.K8sUtils; +import com.imitate.common.sys.constant.SysConfigCsts; +import com.imitate.common.util.TpUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static com.imitate.common.k8s.bean.PodCreateStrategy.MAX_CREATE_POD_TIME_LIMIT; + + +/** + * 代理服务,获取云主机及容器对外映射的端口 + * + * @author 威少 + */ +@Slf4j +@Service +public class ProxyService { + @Autowired + private RunPodService runPodService; + + @Autowired + private K8sService k8sService; + + @Autowired + private PortService portService; + + /** + * 为容器端口创建端口映射,支持外网访问 + * @param tpiID tpiId + * @param podType pod类型 + * @param port 容器端口号 + * @return 外网端口号 + */ + public int getContainerExternalMappingPort(String tpiID, Integer podType, Integer port) { + String cluster = runPodService.getRunPodCluster(tpiID, podType); + String podName = TpUtils.buildEvaPodName(tpiID, podType); + String serviceName = TpUtils.buildEvaServiceName(tpiID, podType, port); + + // 集群或者pod不存在直接报错 + if (StringUtils.isEmpty(cluster) || k8sService.getRunningPod(cluster, podName, MAX_CREATE_POD_TIME_LIMIT) == null) { + log.info("openServicePort failed, pod not ready, tpiID: {}, podType: {}, port: {}", tpiID, podType, port); + throw new BusinessException(ErrorCodeEnum.NOT_CHECK_SVS.getValue(), ErrorCodeEnum.NOT_CHECK_SVS.getDescription()); + } + + // service 存在则直接返回 + io.fabric8.kubernetes.api.model.Service service = k8sService.getService(cluster, serviceName); + if (service != null) { + return K8sUtils.getNodePort(service); + } else { + // 否则创建 + List services = k8sService.getServicesByTpiID(cluster, tpiID); + if (services.size() >= 10) { + throw new BusinessException(ErrorCodeEnum.SVC_PORT_MAX.getValue(), ErrorCodeEnum.SVC_PORT_MAX.getDescription()); + } + int nodePort = portService.allocatePort(SysConfigCsts.KEY_USABLE_PORT_K8S); + k8sService.createService(cluster, serviceName, podName, tpiID, port, nodePort); + return nodePort; + } + } + + + +}