feature(yarn-query,web): 新增 yarn 多集群查询
可以联合或单独查询 yarn 集群,并且聚合过滤排序等数据筛选内容
This commit is contained in:
@@ -7,6 +7,7 @@ package com.lanyuanxiaoyao.service.configuration.entity.yarn;
|
|||||||
* @date 2023-04-19
|
* @date 2023-04-19
|
||||||
*/
|
*/
|
||||||
public final class YarnApplication {
|
public final class YarnApplication {
|
||||||
|
private String cluster;
|
||||||
private String id;
|
private String id;
|
||||||
private String user;
|
private String user;
|
||||||
private String queue;
|
private String queue;
|
||||||
@@ -27,6 +28,15 @@ public final class YarnApplication {
|
|||||||
private Float queueUsagePercentage;
|
private Float queueUsagePercentage;
|
||||||
private Float clusterUsagePercentage;
|
private Float clusterUsagePercentage;
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YarnApplication setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@@ -106,7 +116,8 @@ public final class YarnApplication {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "YarnApplication{" +
|
return "YarnApplication{" +
|
||||||
"id='" + id + '\'' +
|
"cluster='" + cluster + '\'' +
|
||||||
|
", id='" + id + '\'' +
|
||||||
", user='" + user + '\'' +
|
", user='" + user + '\'' +
|
||||||
", queue='" + queue + '\'' +
|
", queue='" + queue + '\'' +
|
||||||
", name='" + name + '\'' +
|
", name='" + name + '\'' +
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package com.lanyuanxiaoyao.service.configuration.entity.yarn;
|
|||||||
* @date 2023-04-22
|
* @date 2023-04-22
|
||||||
*/
|
*/
|
||||||
public final class YarnQueue {
|
public final class YarnQueue {
|
||||||
|
private String cluster;
|
||||||
private String queueName;
|
private String queueName;
|
||||||
private String state;
|
private String state;
|
||||||
private String type;
|
private String type;
|
||||||
@@ -38,6 +39,15 @@ public final class YarnQueue {
|
|||||||
private ResourcesUsed usedAMResource;
|
private ResourcesUsed usedAMResource;
|
||||||
private ResourcesUsed userAMResourceLimit;
|
private ResourcesUsed userAMResourceLimit;
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YarnQueue setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getQueueName() {
|
public String getQueueName() {
|
||||||
return queueName;
|
return queueName;
|
||||||
}
|
}
|
||||||
@@ -161,7 +171,8 @@ public final class YarnQueue {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "YarnQueue{" +
|
return "YarnQueue{" +
|
||||||
"queueName='" + queueName + '\'' +
|
"cluster='" + cluster + '\'' +
|
||||||
|
", queueName='" + queueName + '\'' +
|
||||||
", state='" + state + '\'' +
|
", state='" + state + '\'' +
|
||||||
", type='" + type + '\'' +
|
", type='" + type + '\'' +
|
||||||
", capacity=" + capacity +
|
", capacity=" + capacity +
|
||||||
@@ -180,11 +191,11 @@ public final class YarnQueue {
|
|||||||
", maximumAllocation=" + maximumAllocation +
|
", maximumAllocation=" + maximumAllocation +
|
||||||
", queuePriority=" + queuePriority +
|
", queuePriority=" + queuePriority +
|
||||||
", orderingPolicyInfo='" + orderingPolicyInfo + '\'' +
|
", orderingPolicyInfo='" + orderingPolicyInfo + '\'' +
|
||||||
|
", maxApplications=" + maxApplications +
|
||||||
|
", maxApplicationsPerUser=" + maxApplicationsPerUser +
|
||||||
", numActiveApplications=" + numActiveApplications +
|
", numActiveApplications=" + numActiveApplications +
|
||||||
", numPendingApplications=" + numPendingApplications +
|
", numPendingApplications=" + numPendingApplications +
|
||||||
", numContainers=" + numContainers +
|
", numContainers=" + numContainers +
|
||||||
", maxApplications=" + maxApplications +
|
|
||||||
", maxApplicationsPerUser=" + maxApplicationsPerUser +
|
|
||||||
", userLimit=" + userLimit +
|
", userLimit=" + userLimit +
|
||||||
", userLimitFactor=" + userLimitFactor +
|
", userLimitFactor=" + userLimitFactor +
|
||||||
", configuredMaxAMResourceLimit=" + configuredMaxAMResourceLimit +
|
", configuredMaxAMResourceLimit=" + configuredMaxAMResourceLimit +
|
||||||
|
|||||||
@@ -7,12 +7,22 @@ package com.lanyuanxiaoyao.service.configuration.entity.yarn;
|
|||||||
* @date 2023-04-22
|
* @date 2023-04-22
|
||||||
*/
|
*/
|
||||||
public final class YarnRootQueue {
|
public final class YarnRootQueue {
|
||||||
|
private String cluster;
|
||||||
private String queueName;
|
private String queueName;
|
||||||
private String type;
|
private String type;
|
||||||
private Float capacity;
|
private Float capacity;
|
||||||
private Float usedCapacity;
|
private Float usedCapacity;
|
||||||
private Float maxCapacity;
|
private Float maxCapacity;
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YarnRootQueue setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getQueueName() {
|
public String getQueueName() {
|
||||||
return queueName;
|
return queueName;
|
||||||
}
|
}
|
||||||
@@ -36,7 +46,8 @@ public final class YarnRootQueue {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "YarnRootQueue{" +
|
return "YarnRootQueue{" +
|
||||||
"queueName='" + queueName + '\'' +
|
"cluster='" + cluster + '\'' +
|
||||||
|
", queueName='" + queueName + '\'' +
|
||||||
", type='" + type + '\'' +
|
", type='" + type + '\'' +
|
||||||
", capacity=" + capacity +
|
", capacity=" + capacity +
|
||||||
", usedCapacity=" + usedCapacity +
|
", usedCapacity=" + usedCapacity +
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ import com.dtflys.forest.annotation.BaseRequest;
|
|||||||
* @date 2023-04-21
|
* @date 2023-04-21
|
||||||
*/
|
*/
|
||||||
@BaseRequest(baseURL = "http://service-yarn-query-b1e11")
|
@BaseRequest(baseURL = "http://service-yarn-query-b1e11")
|
||||||
public interface CompactionYarnService extends YarnService {
|
public interface YarnB1Service extends YarnService {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.forest.service;
|
||||||
|
|
||||||
|
import com.dtflys.forest.annotation.BaseRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yarn 信息
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2023-04-21
|
||||||
|
*/
|
||||||
|
@BaseRequest(baseURL = "http://service-yarn-query-b4")
|
||||||
|
public interface YarnB4Service extends YarnService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.forest.service;
|
||||||
|
|
||||||
|
import com.dtflys.forest.annotation.BaseRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yarn 信息
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2023-04-21
|
||||||
|
*/
|
||||||
|
@BaseRequest(baseURL = "http://service-yarn-query-b5")
|
||||||
|
public interface YarnB5Service extends YarnService {
|
||||||
|
}
|
||||||
@@ -9,5 +9,5 @@ import com.dtflys.forest.annotation.BaseRequest;
|
|||||||
* @date 2023-04-21
|
* @date 2023-04-21
|
||||||
*/
|
*/
|
||||||
@BaseRequest(baseURL = "http://service-yarn-query-b2s119")
|
@BaseRequest(baseURL = "http://service-yarn-query-b2s119")
|
||||||
public interface SyncYarnService extends YarnService {
|
public interface YarnB5SyncService extends YarnService {
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,9 @@
|
|||||||
package com.lanyuanxiaoyao.service.web.controller;
|
package com.lanyuanxiaoyao.service.web.controller;
|
||||||
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication;
|
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
|
|
||||||
import com.lanyuanxiaoyao.service.forest.service.YarnService;
|
|
||||||
import com.lanyuanxiaoyao.service.web.entity.YarnApplicationVO;
|
|
||||||
import com.lanyuanxiaoyao.service.web.utils.ComparatorUtil;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import org.eclipse.collections.api.factory.Lists;
|
|
||||||
import org.eclipse.collections.api.factory.Maps;
|
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
|
||||||
import org.eclipse.collections.api.map.ImmutableMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 放一些 Controller 的辅助方法
|
* 放一些 Controller 的辅助方法
|
||||||
@@ -28,12 +14,6 @@ import org.eclipse.collections.api.map.ImmutableMap;
|
|||||||
public class BaseController {
|
public class BaseController {
|
||||||
private static final int SUCCESS_STATUS = 0;
|
private static final int SUCCESS_STATUS = 0;
|
||||||
private static final String SUCCESS_MESSAGE = "OK";
|
private static final String SUCCESS_MESSAGE = "OK";
|
||||||
private static final ImmutableMap<String, Function<YarnApplication, Long>> SORT_MAP = Maps.immutable.of(
|
|
||||||
"startedTime",
|
|
||||||
YarnApplication::getStartedTime,
|
|
||||||
"finishedTime",
|
|
||||||
YarnApplication::getFinishedTime
|
|
||||||
);
|
|
||||||
|
|
||||||
protected AmisResponse responseData() {
|
protected AmisResponse responseData() {
|
||||||
return AmisResponse.builder()
|
return AmisResponse.builder()
|
||||||
@@ -85,73 +65,4 @@ public class BaseController {
|
|||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AmisResponse jobList(
|
|
||||||
YarnService yarnService,
|
|
||||||
Integer page,
|
|
||||||
Integer count,
|
|
||||||
String order,
|
|
||||||
String direction,
|
|
||||||
String filterState,
|
|
||||||
String filterFinalStatus,
|
|
||||||
String searchId,
|
|
||||||
String searchName,
|
|
||||||
// 是否使用精确查询
|
|
||||||
Boolean precise
|
|
||||||
) {
|
|
||||||
boolean isFilterState = StrUtil.isNotBlank(filterState);
|
|
||||||
boolean isFilterFinalStatus = StrUtil.isNotBlank(filterFinalStatus);
|
|
||||||
boolean isSearchId = StrUtil.isNotBlank(searchId);
|
|
||||||
boolean isSearchName = StrUtil.isNotBlank(searchName);
|
|
||||||
Comparator<YarnApplication> comparator = ComparatorUtil.longComparator(order, direction, SORT_MAP);
|
|
||||||
ImmutableList<YarnApplication> applications = yarnService.jobList()
|
|
||||||
.select(app -> !isFilterState || ObjectUtil.contains(filterState, app.getState()))
|
|
||||||
.select(app -> !isFilterFinalStatus || ObjectUtil.contains(filterFinalStatus, app.getFinalStatus()))
|
|
||||||
.select(app -> !isSearchId || (precise ? StrUtil.equals(app.getId(), searchId) : StrUtil.contains(app.getId(), searchId)))
|
|
||||||
.select(app -> !isSearchName || (precise ? StrUtil.equals(app.getName(), searchName) : StrUtil.contains(app.getName(), searchName)))
|
|
||||||
.toSortedList(comparator)
|
|
||||||
.toImmutable();
|
|
||||||
int running = applications.count(app -> ObjectUtil.equal(app.getState(), "RUNNING"));
|
|
||||||
int unRunning = applications.count(app -> ObjectUtil.notEqual(app.getState(), "RUNNING"));
|
|
||||||
ImmutableList<YarnApplicationVO> result = applications
|
|
||||||
.drop(Math.max(page - 1, 0) * count)
|
|
||||||
.take(count)
|
|
||||||
.collect(YarnApplicationVO::new);
|
|
||||||
return responseCrudData(result, applications.size())
|
|
||||||
.withData("running", running)
|
|
||||||
.withData("unRunning", unRunning);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AmisResponse jobCurrent(YarnService yarnService, String name) {
|
|
||||||
Optional<YarnApplication> currentApp = yarnService.jobList()
|
|
||||||
.select(app -> ObjectUtil.equals(app.getName(), name))
|
|
||||||
.select(app -> ObjectUtil.equals(app.getState(), "RUNNING"))
|
|
||||||
.toSortedList(ComparatorUtil.longComparator("startedTime", ComparatorUtil.DESC, SORT_MAP))
|
|
||||||
.getFirstOptional();
|
|
||||||
if (currentApp.isPresent()) {
|
|
||||||
return responseData()
|
|
||||||
.withData("hasCurrent", true)
|
|
||||||
.withData("current", currentApp.get());
|
|
||||||
} else {
|
|
||||||
return responseData().withData("hasCurrent", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AmisResponse queueList(YarnService yarnService, String names) {
|
|
||||||
boolean isFilterNames = StrUtil.isNotBlank(names);
|
|
||||||
ImmutableList<String> filterNames = Lists.immutable.of(names.split(","));
|
|
||||||
ImmutableList<YarnQueue> queues = yarnService.queueList();
|
|
||||||
ImmutableList<YarnQueue> result = queues.select(queue -> !isFilterNames || filterNames.anySatisfy(n -> StrUtil.equals(queue.getQueueName(), n)));
|
|
||||||
return responseCrudData(result, result.size())
|
|
||||||
.withData("queueNames", queues.collect(YarnQueue::getQueueName))
|
|
||||||
.withData("cluster", yarnService.cluster());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AmisResponse queueNames(YarnService yarnService) {
|
|
||||||
return responseData(MapUtil.of("queueNames", yarnService.queueList().collect(YarnQueue::getQueueName)));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AmisResponse cluster(YarnService yarnService) {
|
|
||||||
return responseData(MapUtil.of("cluster", yarnService.cluster()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.web.controller;
|
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
|
||||||
import com.lanyuanxiaoyao.service.forest.service.CompactionYarnService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sync Yarn
|
|
||||||
*
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @date 2023-04-21
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("compaction_yarn")
|
|
||||||
public class CompactionYarnController extends BaseController {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(CompactionYarnController.class);
|
|
||||||
|
|
||||||
private final CompactionYarnService compactionYarnService;
|
|
||||||
|
|
||||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
|
||||||
public CompactionYarnController(CompactionYarnService compactionYarnService) {
|
|
||||||
this.compactionYarnService = compactionYarnService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("job_list")
|
|
||||||
public AmisResponse jobList(
|
|
||||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
|
||||||
@RequestParam(value = "count", defaultValue = "10") Integer count,
|
|
||||||
@RequestParam(value = "order", defaultValue = "startedTime") String order,
|
|
||||||
@RequestParam(value = "direction", defaultValue = "desc") String direction,
|
|
||||||
@RequestParam(value = "filter_state", defaultValue = "") String filterState,
|
|
||||||
@RequestParam(value = "filter_final_status", defaultValue = "") String filterFinalStatus,
|
|
||||||
@RequestParam(value = "search_id", defaultValue = "") String searchId,
|
|
||||||
@RequestParam(value = "search_name", defaultValue = "") String searchName,
|
|
||||||
@RequestParam(value = "precise", defaultValue = "false") Boolean precise
|
|
||||||
) {
|
|
||||||
return jobList(compactionYarnService, page, count, order, direction, filterState, filterFinalStatus, searchId, searchName, precise);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("job_current")
|
|
||||||
public AmisResponse jobCurrent(@RequestParam("name") String name) {
|
|
||||||
return jobCurrent(compactionYarnService, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("queue_list")
|
|
||||||
public AmisResponse queueList(@RequestParam(value = "names", defaultValue = "") String names) {
|
|
||||||
return queueList(compactionYarnService, names);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("queue_names")
|
|
||||||
public AmisResponse queueNames() {
|
|
||||||
return queueNames(compactionYarnService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("cluster")
|
|
||||||
public AmisResponse cluster() {
|
|
||||||
return cluster(compactionYarnService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.web.controller;
|
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
|
||||||
import com.lanyuanxiaoyao.service.forest.service.SyncYarnService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sync Yarn
|
|
||||||
*
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @date 2023-04-21
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("sync_yarn")
|
|
||||||
public class SyncYarnController extends BaseController {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SyncYarnController.class);
|
|
||||||
|
|
||||||
private final SyncYarnService syncYarnService;
|
|
||||||
|
|
||||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
|
||||||
public SyncYarnController(SyncYarnService syncYarnService) {
|
|
||||||
this.syncYarnService = syncYarnService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("job_list")
|
|
||||||
public AmisResponse jobList(
|
|
||||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
|
||||||
@RequestParam(value = "count", defaultValue = "10") Integer count,
|
|
||||||
@RequestParam(value = "order", defaultValue = "startedTime") String order,
|
|
||||||
@RequestParam(value = "direction", defaultValue = "desc") String direction,
|
|
||||||
@RequestParam(value = "filter_state", defaultValue = "") String filterState,
|
|
||||||
@RequestParam(value = "filter_final_status", defaultValue = "") String filterFinalStatus,
|
|
||||||
@RequestParam(value = "search_id", defaultValue = "") String searchId,
|
|
||||||
@RequestParam(value = "search_name", defaultValue = "") String searchName,
|
|
||||||
@RequestParam(value = "precise", defaultValue = "false") Boolean precise
|
|
||||||
) {
|
|
||||||
return jobList(syncYarnService, page, count, order, direction, filterState, filterFinalStatus, searchId, searchName, precise);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("job_current")
|
|
||||||
public AmisResponse jobCurrent(@RequestParam("name") String name) {
|
|
||||||
return jobCurrent(syncYarnService, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("queue_list")
|
|
||||||
public AmisResponse queueList(@RequestParam(value = "names", defaultValue = "") String names) {
|
|
||||||
return queueList(syncYarnService, names);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("queue_names")
|
|
||||||
public AmisResponse queueNames() {
|
|
||||||
return queueNames(syncYarnService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("cluster")
|
|
||||||
public AmisResponse cluster() {
|
|
||||||
return cluster(syncYarnService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,9 @@ import com.eshore.odcp.hudi.connector.entity.TableMeta;
|
|||||||
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
|
import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||||
import com.lanyuanxiaoyao.service.forest.service.CompactionYarnService;
|
|
||||||
import com.lanyuanxiaoyao.service.forest.service.InfoService;
|
import com.lanyuanxiaoyao.service.forest.service.InfoService;
|
||||||
import com.lanyuanxiaoyao.service.forest.service.SyncYarnService;
|
import com.lanyuanxiaoyao.service.forest.service.YarnB1Service;
|
||||||
|
import com.lanyuanxiaoyao.service.forest.service.YarnB5SyncService;
|
||||||
import com.lanyuanxiaoyao.service.web.entity.SyncStateVO;
|
import com.lanyuanxiaoyao.service.web.entity.SyncStateVO;
|
||||||
import com.lanyuanxiaoyao.service.web.entity.TableVO;
|
import com.lanyuanxiaoyao.service.web.entity.TableVO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,14 +41,14 @@ public class TableController extends BaseController {
|
|||||||
private static final Logger logger = LoggerFactory.getLogger(TableController.class);
|
private static final Logger logger = LoggerFactory.getLogger(TableController.class);
|
||||||
private static final ExecutorService EXECUTOR = Executors.newWorkStealingPool(20);
|
private static final ExecutorService EXECUTOR = Executors.newWorkStealingPool(20);
|
||||||
private final InfoService infoService;
|
private final InfoService infoService;
|
||||||
private final SyncYarnService syncYarnService;
|
private final YarnB5SyncService yarnB5SyncService;
|
||||||
private final CompactionYarnService compactionYarnService;
|
private final YarnB1Service yarnB1Service;
|
||||||
|
|
||||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||||
public TableController(InfoService infoService, SyncYarnService syncYarnService, CompactionYarnService compactionYarnService) {
|
public TableController(InfoService infoService, YarnB5SyncService yarnB5SyncService, YarnB1Service yarnB1Service) {
|
||||||
this.infoService = infoService;
|
this.infoService = infoService;
|
||||||
this.syncYarnService = syncYarnService;
|
this.yarnB5SyncService = yarnB5SyncService;
|
||||||
this.compactionYarnService = compactionYarnService;
|
this.yarnB1Service = yarnB1Service;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("list")
|
@GetMapping("list")
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.web.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue;
|
||||||
|
import com.lanyuanxiaoyao.service.forest.service.*;
|
||||||
|
import com.lanyuanxiaoyao.service.web.entity.YarnApplicationVO;
|
||||||
|
import com.lanyuanxiaoyao.service.web.entity.YarnClusterVO;
|
||||||
|
import com.lanyuanxiaoyao.service.web.utils.ComparatorUtil;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import org.eclipse.collections.api.factory.Lists;
|
||||||
|
import org.eclipse.collections.api.factory.Maps;
|
||||||
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
|
import org.eclipse.collections.api.map.ImmutableMap;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync Yarn
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2023-04-21
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("yarn")
|
||||||
|
public class YarnController extends BaseController {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(YarnController.class);
|
||||||
|
private static final ExecutorService EXECUTOR = Executors.newWorkStealingPool(20);
|
||||||
|
private static final ImmutableMap<String, Function<YarnApplication, Long>> SORT_MAP = Maps.immutable.of(
|
||||||
|
"startedTime",
|
||||||
|
YarnApplication::getStartedTime,
|
||||||
|
"finishedTime",
|
||||||
|
YarnApplication::getFinishedTime
|
||||||
|
);
|
||||||
|
private final ImmutableMap<String, YarnService> yarnServices;
|
||||||
|
|
||||||
|
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||||
|
public YarnController(YarnB1Service yarnB1Service, YarnB5SyncService yarnB5SyncService, YarnB4Service yarnB4Service, YarnB5Service yarnB5Service) {
|
||||||
|
yarnServices = Maps.immutable.ofAll(MapUtil.<String, YarnService>builder()
|
||||||
|
.put("b1", yarnB1Service)
|
||||||
|
.put("b5-sync", yarnB5SyncService)
|
||||||
|
.put("b4", yarnB4Service)
|
||||||
|
.put("b5", yarnB5Service)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private YarnService getService(String cluster) {
|
||||||
|
if (!yarnServices.containsKey(cluster)) {
|
||||||
|
throw new RuntimeException(StrUtil.format("Cluster {} not found", cluster));
|
||||||
|
}
|
||||||
|
return yarnServices.get(cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableList<YarnService> getServices(List<String> clusters) {
|
||||||
|
return Lists.immutable.ofAll(clusters).collect(this::getService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("job_list")
|
||||||
|
public AmisResponse jobList(
|
||||||
|
@RequestParam("clusters") List<String> clusters,
|
||||||
|
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||||
|
@RequestParam(value = "count", defaultValue = "10") Integer count,
|
||||||
|
@RequestParam(value = "order", defaultValue = "startedTime") String order,
|
||||||
|
@RequestParam(value = "direction", defaultValue = "desc") String direction,
|
||||||
|
@RequestParam(value = "filter_state", defaultValue = "") String filterState,
|
||||||
|
@RequestParam(value = "filter_final_status", defaultValue = "") String filterFinalStatus,
|
||||||
|
@RequestParam(value = "search_id", defaultValue = "") String searchId,
|
||||||
|
@RequestParam(value = "search_name", defaultValue = "") String searchName,
|
||||||
|
@RequestParam(value = "precise", defaultValue = "false") Boolean precise
|
||||||
|
) {
|
||||||
|
boolean isFilterState = StrUtil.isNotBlank(filterState);
|
||||||
|
boolean isFilterFinalStatus = StrUtil.isNotBlank(filterFinalStatus);
|
||||||
|
boolean isSearchId = StrUtil.isNotBlank(searchId);
|
||||||
|
boolean isSearchName = StrUtil.isNotBlank(searchName);
|
||||||
|
Comparator<YarnApplication> comparator = ComparatorUtil.longComparator(order, direction, SORT_MAP);
|
||||||
|
ImmutableList<YarnApplication> applications = getServices(clusters)
|
||||||
|
.asParallel(EXECUTOR, 1)
|
||||||
|
.flatCollect(YarnService::jobList)
|
||||||
|
.select(app -> !isFilterState || ObjectUtil.contains(filterState, app.getState()))
|
||||||
|
.select(app -> !isFilterFinalStatus || ObjectUtil.contains(filterFinalStatus, app.getFinalStatus()))
|
||||||
|
.select(app -> !isSearchId || (precise ? StrUtil.equals(app.getId(), searchId) : StrUtil.contains(app.getId(), searchId)))
|
||||||
|
.select(app -> !isSearchName || (precise ? StrUtil.equals(app.getName(), searchName) : StrUtil.contains(app.getName(), searchName)))
|
||||||
|
.toSortedList(comparator)
|
||||||
|
.toImmutable();
|
||||||
|
int running = applications.count(app -> ObjectUtil.equal(app.getState(), "RUNNING"));
|
||||||
|
int unRunning = applications.count(app -> ObjectUtil.notEqual(app.getState(), "RUNNING"));
|
||||||
|
ImmutableList<YarnApplicationVO> result = applications
|
||||||
|
.drop(Math.max(page - 1, 0) * count)
|
||||||
|
.take(count)
|
||||||
|
.collect(YarnApplicationVO::new);
|
||||||
|
return responseCrudData(result, applications.size())
|
||||||
|
.withData("running", running)
|
||||||
|
.withData("unRunning", unRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("job_current")
|
||||||
|
public AmisResponse jobCurrent(@RequestParam("clusters") List<String> clusters, @RequestParam("name") String name) {
|
||||||
|
Optional<YarnApplication> currentApp = getServices(clusters)
|
||||||
|
.asParallel(EXECUTOR, 1)
|
||||||
|
.flatCollect(YarnService::jobList)
|
||||||
|
.select(app -> ObjectUtil.equals(app.getName(), name))
|
||||||
|
.select(app -> ObjectUtil.equals(app.getState(), "RUNNING"))
|
||||||
|
.toSortedList(ComparatorUtil.longComparator("startedTime", ComparatorUtil.DESC, SORT_MAP))
|
||||||
|
.getFirstOptional();
|
||||||
|
if (currentApp.isPresent()) {
|
||||||
|
return responseData()
|
||||||
|
.withData("hasCurrent", true)
|
||||||
|
.withData("current", currentApp.get());
|
||||||
|
} else {
|
||||||
|
return responseData().withData("hasCurrent", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("queue_list")
|
||||||
|
public AmisResponse queueList(@RequestParam("clusters") List<String> clusters, @RequestParam(value = "names", defaultValue = "") String names) {
|
||||||
|
boolean isFilterNames = StrUtil.isNotBlank(names);
|
||||||
|
ImmutableList<String> filterNames = Lists.immutable.of(names.split(","));
|
||||||
|
ImmutableList<YarnClusterVO> results = getServices(clusters)
|
||||||
|
.asParallel(EXECUTOR, 1)
|
||||||
|
.collect(yarnService -> {
|
||||||
|
YarnRootQueue cluster = yarnService.cluster();
|
||||||
|
ImmutableList<YarnQueue> queues = yarnService.queueList().select(queue -> !isFilterNames || filterNames.anySatisfy(n -> StrUtil.equals(queue.getQueueName(), n)));
|
||||||
|
return new YarnClusterVO(cluster, queues);
|
||||||
|
})
|
||||||
|
.toList()
|
||||||
|
.toImmutable();
|
||||||
|
return responseCrudData(results, results.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("queue_names")
|
||||||
|
public AmisResponse queueNames(@RequestParam("clusters") List<String> clusters) {
|
||||||
|
return responseData(MapUtil.of("queueNames", getServices(clusters).flatCollect(YarnService::queueList).collect(YarnQueue::getQueueName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("clusters")
|
||||||
|
public AmisResponse clusters(@RequestParam("clusters") List<String> clusters) {
|
||||||
|
return responseData(MapUtil.of("cluster", getServices(clusters).collect(YarnService::cluster)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,10 @@ public class YarnApplicationVO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return yarnApplication.getCluster();
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return yarnApplication.getId();
|
return yarnApplication.getId();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.web.entity;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
|
||||||
|
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue;
|
||||||
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2023-05-05
|
||||||
|
*/
|
||||||
|
public class YarnClusterVO {
|
||||||
|
@JsonIgnore
|
||||||
|
private final YarnRootQueue yarnRootQueue;
|
||||||
|
private final ImmutableList<YarnQueue> children;
|
||||||
|
|
||||||
|
public YarnClusterVO(YarnRootQueue yarnRootQueue, ImmutableList<YarnQueue> children) {
|
||||||
|
this.yarnRootQueue = yarnRootQueue;
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isRoot() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return yarnRootQueue.getCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQueueName() {
|
||||||
|
return StrUtil.format("{} ({})", yarnRootQueue.getQueueName(), yarnRootQueue.getCluster());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return yarnRootQueue.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getAbsoluteCapacity() {
|
||||||
|
return yarnRootQueue.getCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getAbsoluteUsedCapacity() {
|
||||||
|
return yarnRootQueue.getUsedCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getAbsoluteMaxCapacity() {
|
||||||
|
return yarnRootQueue.getMaxCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableList<YarnQueue> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "YarnClusterVO{" +
|
||||||
|
"yarnRootQueue=" + yarnRootQueue +
|
||||||
|
", yarnQueues=" + children +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,9 @@ function cloudTab() {
|
|||||||
type: 'crud',
|
type: 'crud',
|
||||||
title: '服务列表',
|
title: '服务列表',
|
||||||
api: '${base}/cloud/list',
|
api: '${base}/cloud/list',
|
||||||
source: '$items',
|
interval: 2000,
|
||||||
|
syncLocation: false,
|
||||||
|
silentPolling: true,
|
||||||
headerToolbar: ['reload'],
|
headerToolbar: ['reload'],
|
||||||
columns: [
|
columns: [
|
||||||
{name: 'name', label: '名称'},
|
{name: 'name', label: '名称'},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ function yarnCrudColumns() {
|
|||||||
{
|
{
|
||||||
name: 'id',
|
name: 'id',
|
||||||
label: 'ID',
|
label: 'ID',
|
||||||
width: 240,
|
width: 250,
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
...copyField('id')
|
...copyField('id')
|
||||||
},
|
},
|
||||||
@@ -21,12 +21,19 @@ function yarnCrudColumns() {
|
|||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
...copyField('name')
|
...copyField('name')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'cluster',
|
||||||
|
label: '集群',
|
||||||
|
width: 50,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '用户',
|
label: '用户',
|
||||||
width: 80,
|
width: 80,
|
||||||
type: 'tooltip-wrapper',
|
type: 'tooltip-wrapper',
|
||||||
body: '${TRUNCATE(user, 8)}',
|
body: '${TRUNCATE(user, 8)}',
|
||||||
content: '${user}',
|
content: '${user}',
|
||||||
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'startedTime',
|
name: 'startedTime',
|
||||||
@@ -162,7 +169,7 @@ function yarnCrudColumns() {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function simpleYarnDialog(mode, title) {
|
function simpleYarnDialog(cluster, title, filterField) {
|
||||||
return {
|
return {
|
||||||
title: title,
|
title: title,
|
||||||
actions: [],
|
actions: [],
|
||||||
@@ -194,8 +201,9 @@ function simpleYarnDialog(mode, title) {
|
|||||||
type: 'crud',
|
type: 'crud',
|
||||||
api: {
|
api: {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `\${base}/${mode}_yarn/job_list`,
|
url: `\${base}/yarn/job_list`,
|
||||||
data: {
|
data: {
|
||||||
|
clusters: `${cluster}`,
|
||||||
page: '${page|default:undefined}',
|
page: '${page|default:undefined}',
|
||||||
count: '${perPage|default:undefined}',
|
count: '${perPage|default:undefined}',
|
||||||
order: '${orderBy|default:undefined}',
|
order: '${orderBy|default:undefined}',
|
||||||
@@ -203,7 +211,7 @@ function simpleYarnDialog(mode, title) {
|
|||||||
filter_state: '${state|default:undefined}',
|
filter_state: '${state|default:undefined}',
|
||||||
filter_final_status: '${finalStatus|default:undefined}',
|
filter_final_status: '${finalStatus|default:undefined}',
|
||||||
search_id: '${id|default:undefined}',
|
search_id: '${id|default:undefined}',
|
||||||
search_name: `\${${mode}JobName}`,
|
search_name: `\${${filterField}}`,
|
||||||
precise: true,
|
precise: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -286,7 +294,7 @@ function flinkJobDialog() {
|
|||||||
type: 'action',
|
type: 'action',
|
||||||
label: '打开同步详情',
|
label: '打开同步详情',
|
||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: simpleYarnDialog('sync', '同步详情')
|
dialog: simpleYarnDialog('b5-sync', '同步详情', 'syncJobName')
|
||||||
},
|
},
|
||||||
{type: 'divider'},
|
{type: 'divider'},
|
||||||
{
|
{
|
||||||
@@ -386,14 +394,14 @@ function tableMetaDialog() {
|
|||||||
type: 'action',
|
type: 'action',
|
||||||
icon: 'fa fa-arrows-rotate',
|
icon: 'fa fa-arrows-rotate',
|
||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: simpleYarnDialog('sync', '同步详情')
|
dialog: simpleYarnDialog('b5-sync', '同步详情', 'syncJobName')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '压缩情况',
|
label: '压缩情况',
|
||||||
type: 'action',
|
type: 'action',
|
||||||
icon: 'fa fa-minimize',
|
icon: 'fa fa-minimize',
|
||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: simpleYarnDialog('compaction', '压缩详情')
|
dialog: simpleYarnDialog('b1', '压缩详情', 'compactionJobName')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'button',
|
type: 'button',
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
function yarnTab(name, title, queueNames = 'default', searchName = undefined) {
|
function yarnTab(cluster, title, queueNames = 'default', searchName = undefined) {
|
||||||
return {
|
return {
|
||||||
title: `${title} 集群`,
|
title: `${title} 集群`,
|
||||||
tab: [
|
tab: [
|
||||||
{
|
{
|
||||||
id: `${name}-yarn-service`,
|
id: `${cluster}-yarn-service`,
|
||||||
name: `${name}-yarn-service`,
|
name: `${cluster}-yarn-service`,
|
||||||
type: 'service',
|
type: 'service',
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
type: 'tpl',
|
type: 'tpl',
|
||||||
tpl: '<span class="font-bold text-xl">集群资源</span>',
|
tpl: '<span class="font-bold text-xl">集群资源</span>',
|
||||||
// className: 'mb-2 block',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'crud',
|
type: 'crud',
|
||||||
api: {
|
api: {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `\${base}/${name}_yarn/queue_list`,
|
url: '${base}/yarn/queue_list',
|
||||||
data: {
|
data: {
|
||||||
|
clusters: `${cluster}`,
|
||||||
names: '${queueName|default:undefined}'
|
names: '${queueName|default:undefined}'
|
||||||
},
|
},
|
||||||
responseData: {
|
|
||||||
'&': '$$',
|
|
||||||
clusterUsage: '${ROUND((cluster.usedCapacity * 100 / cluster.maxCapacity), 0)}'
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
defaultParams: {
|
defaultParams: {
|
||||||
queueName: queueNames,
|
queueName: queueNames,
|
||||||
@@ -33,10 +29,6 @@ function yarnTab(name, title, queueNames = 'default', searchName = undefined) {
|
|||||||
silentPolling: true,
|
silentPolling: true,
|
||||||
headerToolbar: [
|
headerToolbar: [
|
||||||
"reload",
|
"reload",
|
||||||
{
|
|
||||||
type: "tpl",
|
|
||||||
tpl: "集群总资源 <span class='ml-1 font-extrabold text-xl ${IF(clusterUsage > 0, IF(clusterUsage > 30, IF(clusterUsage > 90, 'text-danger', 'text-info'), 'text-info'), 'text-success')}'>${clusterUsage}%</span>"
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
@@ -86,6 +78,7 @@ function yarnTab(name, title, queueNames = 'default', searchName = undefined) {
|
|||||||
type: "button",
|
type: "button",
|
||||||
level: "link",
|
level: "link",
|
||||||
tooltip: '查看队列详情',
|
tooltip: '查看队列详情',
|
||||||
|
visibleOn: '${!root}',
|
||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: {
|
dialog: {
|
||||||
closeOnEsc: true,
|
closeOnEsc: true,
|
||||||
@@ -141,8 +134,9 @@ function yarnTab(name, title, queueNames = 'default', searchName = undefined) {
|
|||||||
type: 'crud',
|
type: 'crud',
|
||||||
api: {
|
api: {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `\${base}/${name}_yarn/job_list`,
|
url: '${base}/yarn/job_list',
|
||||||
data: {
|
data: {
|
||||||
|
clusters: `${cluster}`,
|
||||||
page: '${page|default:undefined}',
|
page: '${page|default:undefined}',
|
||||||
count: '${perPage|default:undefined}',
|
count: '${perPage|default:undefined}',
|
||||||
order: '${orderBy|default:undefined}',
|
order: '${orderBy|default:undefined}',
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
/>
|
/>
|
||||||
<title>Hudi 服务页面</title>
|
<title>Hudi 服务页面</title>
|
||||||
<link href="sdk/sdk-icon.css" rel="stylesheet"/>
|
<link href="sdk/sdk-icon.css" rel="stylesheet"/>
|
||||||
<!-- <link href="sdk/default.css" rel="stylesheet"/>-->
|
<!-- <link href="sdk/default.css" rel="stylesheet"/>-->
|
||||||
<!-- <link href="sdk/fontawesome.css" rel="stylesheet"/>-->
|
<!-- <link href="sdk/fontawesome.css" rel="stylesheet"/>-->
|
||||||
<link href="sdk/ang.css" rel="stylesheet"/>
|
<link href="sdk/ang.css" rel="stylesheet"/>
|
||||||
<!-- <link href="sdk/cxd.css" rel="stylesheet"/>-->
|
<!-- <link href="sdk/cxd.css" rel="stylesheet"/>-->
|
||||||
<!-- <link href="sdk/antd.css" rel="stylesheet"/>-->
|
<!-- <link href="sdk/antd.css" rel="stylesheet"/>-->
|
||||||
<link href="sdk/helper.css" rel="stylesheet"/>
|
<link href="sdk/helper.css" rel="stylesheet"/>
|
||||||
<link href="sdk/iconfont.css" rel="stylesheet"/>
|
<link href="sdk/iconfont.css" rel="stylesheet"/>
|
||||||
<link href="sdk/fontawesome.css" rel="stylesheet"/>
|
<link href="sdk/fontawesome.css" rel="stylesheet"/>
|
||||||
@@ -52,8 +52,11 @@
|
|||||||
tabsMode: 'strong',
|
tabsMode: 'strong',
|
||||||
tabs: [
|
tabs: [
|
||||||
tableTab(),
|
tableTab(),
|
||||||
yarnTab('sync', 'Sync'),
|
yarnTab('b5-sync', '同步 b5', undefined, 'Sync'),
|
||||||
yarnTab('compaction', 'Compaction', 'datalake,tyly', 'Compaction'),
|
yarnTab(' b1,b4,b5', '压缩 b1 b4 b5', 'datalake,tyly'),
|
||||||
|
yarnTab(' b1', '压缩 b1', 'datalake,tyly', 'Compaction'),
|
||||||
|
yarnTab(' b4', '压缩 b4'),
|
||||||
|
yarnTab(' b5', '压缩 b5'),
|
||||||
cloudTab(),
|
cloudTab(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,17 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("yarn")
|
@ConfigurationProperties("yarn")
|
||||||
public class YarnConfiguration {
|
public class YarnConfiguration {
|
||||||
|
private String cluster;
|
||||||
private String webUrl;
|
private String webUrl;
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
}
|
||||||
|
|
||||||
public String getWebUrl() {
|
public String getWebUrl() {
|
||||||
return webUrl;
|
return webUrl;
|
||||||
}
|
}
|
||||||
@@ -25,7 +34,8 @@ public class YarnConfiguration {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "YarnConfiguration{" +
|
return "YarnConfiguration{" +
|
||||||
"webUrl='" + webUrl + '\'' +
|
"cluster='" + cluster + '\'' +
|
||||||
|
", webUrl='" + webUrl + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,6 @@ public class ClusterServiceImpl implements ClusterService {
|
|||||||
public YarnRootQueue info() throws JsonProcessingException {
|
public YarnRootQueue info() throws JsonProcessingException {
|
||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
||||||
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
||||||
return mapper.readValue(body, ClusterInfoResponse.class).getScheduler().getSchedulerInfo();
|
return mapper.readValue(body, ClusterInfoResponse.class).getScheduler().getSchedulerInfo().setCluster(yarnConfiguration.getCluster());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class JobAutoRefreshServiceImpl implements JobService {
|
|||||||
public void refresh() throws JsonProcessingException {
|
public void refresh() throws JsonProcessingException {
|
||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps");
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps");
|
||||||
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
||||||
ImmutableList<YarnApplication> apps = mapper.readValue(body, ApplicationsListResponse.class).getApps().getApp();
|
ImmutableList<YarnApplication> apps = mapper.readValue(body, ApplicationsListResponse.class).getApps().getApp().tap(app -> app.setCluster(yarnConfiguration.getCluster()));
|
||||||
CACHE.set(apps);
|
CACHE.set(apps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class JobServiceImpl implements JobService {
|
|||||||
public ImmutableList<YarnApplication> list() throws JsonProcessingException {
|
public ImmutableList<YarnApplication> list() throws JsonProcessingException {
|
||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps");
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps");
|
||||||
try (HttpResponse response = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute()) {
|
try (HttpResponse response = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute()) {
|
||||||
return mapper.readValue(response.body(), ApplicationsListResponse.class).getApps().getApp();
|
return mapper.readValue(response.body(), ApplicationsListResponse.class).getApps().getApp().tap(app -> app.setCluster(yarnConfiguration.getCluster()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,14 +52,14 @@ public class JobServiceImpl implements JobService {
|
|||||||
@Retryable(Throwable.class)
|
@Retryable(Throwable.class)
|
||||||
@Override
|
@Override
|
||||||
public ImmutableList<YarnApplication> listEquals(String name) throws JsonProcessingException {
|
public ImmutableList<YarnApplication> listEquals(String name) throws JsonProcessingException {
|
||||||
return list().select(app -> StrUtil.equals(app.getName(), name));
|
return list().select(app -> StrUtil.equals(app.getName(), name)).tap(app -> app.setCluster(yarnConfiguration.getCluster()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cacheable(value = "job-list", sync = true, key = "#{methodName+name}")
|
@Cacheable(value = "job-list", sync = true, key = "#{methodName+name}")
|
||||||
@Retryable(Throwable.class)
|
@Retryable(Throwable.class)
|
||||||
@Override
|
@Override
|
||||||
public ImmutableList<YarnApplication> listLike(String name) throws JsonProcessingException {
|
public ImmutableList<YarnApplication> listLike(String name) throws JsonProcessingException {
|
||||||
return list().select(app -> StrUtil.contains(app.getName(), name));
|
return list().select(app -> StrUtil.contains(app.getName(), name)).tap(app -> app.setCluster(yarnConfiguration.getCluster()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,7 +72,7 @@ public class JobServiceImpl implements JobService {
|
|||||||
public YarnApplication detail(String applicationId) throws JsonProcessingException {
|
public YarnApplication detail(String applicationId) throws JsonProcessingException {
|
||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps/" + applicationId);
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/apps/" + applicationId);
|
||||||
try (HttpResponse response = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute()) {
|
try (HttpResponse response = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute()) {
|
||||||
return mapper.readValue(response.body(), ApplicationDetailResponse.class).getApp();
|
return mapper.readValue(response.body(), ApplicationDetailResponse.class).getApp().setCluster(yarnConfiguration.getCluster());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ public class QueueAutoRefreshServiceImpl implements QueueService {
|
|||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
||||||
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
||||||
QueueListResponse response = mapper.readValue(body, QueueListResponse.class);
|
QueueListResponse response = mapper.readValue(body, QueueListResponse.class);
|
||||||
ImmutableList<YarnQueue> queues = Lists.immutable.ofAll(response.getScheduler().getSchedulerInfo().getQueues().getQueue());
|
ImmutableList<YarnQueue> queues = Lists.immutable.ofAll(response.getScheduler().getSchedulerInfo().getQueues().getQueue())
|
||||||
|
.tap(q -> q.setCluster(yarnConfiguration.getCluster()));
|
||||||
CACHE.set(queues);
|
CACHE.set(queues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class QueueServiceImpl implements QueueService {
|
|||||||
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
String queryUrl = URLUtil.completeUrl(yarnConfiguration.getWebUrl(), "/ws/v1/cluster/scheduler");
|
||||||
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
|
||||||
QueueListResponse response = mapper.readValue(body, QueueListResponse.class);
|
QueueListResponse response = mapper.readValue(body, QueueListResponse.class);
|
||||||
return Lists.immutable.ofAll(response.getScheduler().getSchedulerInfo().getQueues().getQueue());
|
return Lists.immutable.ofAll(response.getScheduler().getSchedulerInfo().getQueues().getQueue()).tap(q -> q.setCluster(yarnConfiguration.getCluster()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cacheable(value = "queue-detail", sync = true, key = "#name")
|
@Cacheable(value = "queue-detail", sync = true, key = "#name")
|
||||||
@@ -54,6 +54,7 @@ public class QueueServiceImpl implements QueueService {
|
|||||||
return list()
|
return list()
|
||||||
.select(q -> StrUtil.equals(q.getQueueName(), name))
|
.select(q -> StrUtil.equals(q.getQueueName(), name))
|
||||||
.getFirstOptional()
|
.getFirstOptional()
|
||||||
.orElseThrow(() -> new Exception("cannot found " + name));
|
.orElseThrow(() -> new Exception("cannot found " + name))
|
||||||
|
.setCluster(yarnConfiguration.getCluster());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user