Browse Source

增加服务预览与vscode增加语言

master
educoder 2 years ago
parent
commit
d4707385c3
4 changed files with 274 additions and 1 deletions
  1. +15
    -1
      web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java
  2. +153
    -0
      web/src/main/java/com/imitate/web/module/game/controller/WebController.java
  3. +104
    -0
      web/src/main/java/com/imitate/web/module/game/service/WebService.java
  4. +2
    -0
      web/src/main/java/com/imitate/web/params/GetVsCodeParam.java

+ 15
- 1
web/src/main/java/com/imitate/web/module/game/controller/VscodeController.java View File

@@ -47,6 +47,10 @@ import java.util.Map;
@RequestMapping("/vscode")
public class VscodeController extends BasicController {
private final Logger logger = LoggerFactory.getLogger(getClass());

private static final String C_IMAGE_NAME = "gcc-codeserver-ww";
private static final String JAVA_IMAGE_NAME = "vscode-ww";
private static final String PYTHON_IMAGE_NAME = "python3d7-codeserver";

@Autowired
@@ -97,10 +101,20 @@ public class VscodeController extends BasicController {
//若不是正确镜像则给出提示 目前支持java/c/python环境
JSONObject mainContainer = ContainerUtil.getMainContainer(containers);
String imageName = mainContainer.getString("imageName");
if (!CollectionUtil.toList("vscode-ww", "gcc-codeserver-ww", "python3d7-codeserver").contains(imageName)) {
if (!CollectionUtil.toList(C_IMAGE_NAME, JAVA_IMAGE_NAME, PYTHON_IMAGE_NAME).contains(imageName)) {
return R.error("-3", "错误的镜像名称:" + imageName);
}

if ("c".equals(vsCodeParam.getLanguage().toLowerCase(Locale.ROOT))){
imageName = C_IMAGE_NAME + ":v1.0";
}else if("java".equals(vsCodeParam.getLanguage().toLowerCase(Locale.ROOT))){
imageName = JAVA_IMAGE_NAME + ":v1.0";
}else if("python".equals(vsCodeParam.getLanguage().toLowerCase(Locale.ROOT))){
imageName = PYTHON_IMAGE_NAME + ":v1.0";
}

//根据语言替换镜像名
mainContainer.put("imageName",imageName);

boolean createImage = vsCodeParam.getCreateImage() != null && vsCodeParam.getCreateImage();



+ 153
- 0
web/src/main/java/com/imitate/web/module/game/controller/WebController.java View File

@@ -0,0 +1,153 @@
package com.imitate.web.module.game.controller;


import com.alibaba.fastjson.JSONObject;
import com.imitate.common.annotation.PublicUrl;
import com.imitate.common.k8s.mgr.ClusterManager;
import com.imitate.common.k8s.pojo.RunPod;
import com.imitate.common.k8s.service.DiskService;
import com.imitate.common.k8s.service.RunPodService;
import com.imitate.common.util.Base64Util;
import com.imitate.common.util.R;
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.WebService;
import com.imitate.web.module.game.thread.code.LocalCheckJob;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;


/**
* @author 悟空
* @date 2022/04/12
*/
@Api(value = "web控制器", hidden = true)
@RestController
@RequestMapping("/web")
public class WebController {


private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private WebService webService;

@Autowired
private ClusterManager clusterManager;

@Autowired
private GitService gitService;

@Autowired
private GameService gameService;

@Autowired
private RunPodService runPodService;

@Autowired
private DiskService diskService;

@Qualifier("gitTaskExecutor")
@Autowired
private ThreadPoolTaskExecutor gitTaskExecutor;


@PublicUrl(signValidate = true)
@RequestMapping(path = "/getWebsvc")
@ApiOperation(value = "getWebsvc", httpMethod = "POST", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R getWebsvc(
@ApiParam(name = "tpiID", required = true, value = "tpiID") @RequestParam String tpiID,
@ApiParam(name = "podType", required = true, value = "pod类型,0为evaluate, 1为webssh,2为evassh") @RequestParam Integer podType,
@ApiParam(name = "tpiGitURL", required = false, value = "tpi版本库地址") String tpiGitURL,
@ApiParam(name = "containers", required = true, value = "需要使用的容器,base64编码") @RequestParam String containers,
@ApiParam(name = "router", required = false, value = "容器内部服务启动的路由地址") @RequestParam(defaultValue = "") String router,
@ApiParam(name = "needPortMapping", required = false, value = "容器中需要被映射的端口") Integer needPortMapping,
@ApiParam(name = "bigDataFile", required = false, value = "大数据集文件") String bigDataFile,
@ApiParam(name = "createImage", required = false, value = "是否为创建镜像") Boolean createImage,
@ApiParam(name = "survivalSecond", required = false, value = "存活秒数") Integer survivalSecond) throws Exception {
logger.info("[start]获取web service连接信息,tpiID: {}, podType: {},containers: {}, tpiGitURL: {},needPortMapping: {}, bigDataFile: {}, createImage: {}, survivalSecond: {},router:{}",
tpiID, podType, containers,tpiGitURL, needPortMapping, bigDataFile, createImage, survivalSecond,router);

//若容器为数组
if("W10=".equals(containers)){
return R.error(-3,"容器为空数组");
}

containers = Base64Util.decode(containers);


createImage = createImage != null && createImage;
JSONObject response = new JSONObject();


//指定默认集群
String cluster = "local";

// 检查本地版本库
if (StringUtils.isNotEmpty(tpiGitURL)) {
if (clusterManager.isLocalCluster(cluster)) {
String tpiWorkspace = diskService.getTpiWorkspaceHostPath(tpiID);
boolean localCodeExist = gameService.checkLocalCodeExist(tpiID, tpiGitURL, tpiWorkspace);
tpiGitURL = Base64Util.decode(tpiGitURL);
if (!localCodeExist) {
// 下载本地版本库
LocalCheckJob localCheckJob = gameService.getLocalCheckJob(tpiID, tpiGitURL, tpiWorkspace);
gitTaskExecutor.execute(localCheckJob);
}
} else {
String finalTpiGitURL = tpiGitURL;
gitTaskExecutor.execute(new Runnable() {
@Override
public void run() {
gitService.remoteClusterCheckCode(cluster, Boolean.TRUE, tpiID, finalTpiGitURL);
}
});
}
}

//返回web服务路径地址
String targetUrl = webService.getWebService(cluster,tpiID,podType, containers, bigDataFile, survivalSecond, createImage, needPortMapping,router);

// 环境存在问题则重新获取创建一次
if (targetUrl == null) {
targetUrl = webService.getWebService(cluster,tpiID,podType,containers, bigDataFile, survivalSecond, createImage, needPortMapping,router);
}

if(targetUrl != null){
//测试能否访问
int timeout = 120;
while (webService.testWsdlConnection(targetUrl) != 200 && webService.testWsdlConnection(targetUrl) != 302 && timeout > 0){
Thread.sleep(1000);
timeout--;
}

if(webService.testWsdlConnection(targetUrl) != 200 && webService.testWsdlConnection(targetUrl) != 302 && timeout <= 0){
return R.error(-4,"服务链接: " + targetUrl +" 无法正常访问。");
}
}

if(targetUrl == null) {
return R.error(-5,"当前实验使用的用户较多,系统正在智能化为您调度更优质的资源,预计一分钟内完成,请稍后重试!");
}else{
String podName = TpUtils.buildWebPodName(tpiID, podType);
RunPod runPod = runPodService.getRunPodByName(podName);
//存活秒数
response.put("remainingTime",webService.getRemainingTime(runPod));
response.put("url",targetUrl);
}
return R.ok().setData(response);
}


}

+ 104
- 0
web/src/main/java/com/imitate/web/module/game/service/WebService.java View File

@@ -0,0 +1,104 @@
package com.imitate.web.module.game.service;



import com.imitate.common.k8s.pojo.RunPod;
import com.imitate.common.k8s.service.DiskService;
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.sys.service.SysConfigService;
import com.imitate.common.sys.settings.AppConfig;
import com.imitate.common.util.TpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.HttpURLConnection;
import java.net.URL;
import java.time.ZoneOffset;



/**
* web
* @author 悟空
*/
@Service("webService")
public class WebService {
private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private K8sService k8sService;
@Autowired
private AppConfig appConfig;
@Autowired
private PortService portService;
@Autowired
private RunPodService runPodService;
@Autowired
private SysConfigService sysConfigService;
@Autowired
private DiskService diskService;

/**
* 获取服务
*/
public String getServicePort(final String cluster, String tpiID, Integer podType, Integer port) {
String podName = TpUtils.buildWebPodName(tpiID, podType);
String serviceName = podName + "-" + port;

// 查询
io.fabric8.kubernetes.api.model.Service service = k8sService.getService(cluster, serviceName);

// 查询不到创建
if (service == null) {
String svcPort = portService.allocatePort(SysConfigCsts.KEY_USABLE_PORT_K8S) + "";
k8sService.createService(cluster, serviceName, podName, tpiID, port, Integer.parseInt(svcPort));
runPodService.updateRunPodSshPort(podName, svcPort);
return svcPort;
} else {
return String.valueOf(K8sUtils.getNodePort(service));
}

}

public String getWebService(String cluster,String tpiID,Integer podType, String containers, String bigDataFile, Integer survivalSecond, Boolean createImage, Integer needPortMapping,String router) throws InterruptedException {
// 获取web service服务外部暴露端口
String webSvcPort = getServicePort(cluster, tpiID, podType, needPortMapping);
return "https://" + webSvcPort + appConfig.getVscodeDomain() + router;
}

public int testWsdlConnection(String address) throws Exception {
int status = 404;
try {
URL urlObj = new URL(address);
HttpURLConnection oc = (HttpURLConnection) urlObj.openConnection();
oc.setUseCaches(false);
oc.setConnectTimeout(3000); // 设置超时时间
status = oc.getResponseCode();// 请求状态
if (200 == status) {
// 200是请求地址顺利连通。。
return status;
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return status;
}


/**
* 获取实例剩余时间
* @param
* @return 连接剩余时间
*/
public long getRemainingTime(RunPod runPod) {
return runPod.getExpireTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() - System.currentTimeMillis();
}

}

+ 2
- 0
web/src/main/java/com/imitate/web/params/GetVsCodeParam.java View File

@@ -27,4 +27,6 @@ public class GetVsCodeParam {
private String projectId;
@NotBlank(message = "用户ID不能为空")
private String userId;
@NotBlank(message = "语言不能为空")
private String language;
}

Loading…
Cancel
Save