From b7956c6bb4f4680a0714d19a58ba264f7ac9123a Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Mon, 4 Mar 2019 19:46:53 +0800 Subject: [PATCH] dashboard: code and document refinement Signed-off-by: Eric Zhao --- .../Sentinel_Dashboard_Feature.md | 19 ++++--- sentinel-dashboard/pom.xml | 28 +++++----- .../dashboard/config/DashboardConfig.java | 14 +++-- .../dashboard/controller/AppController.java | 33 +++++------- .../controller/MachineRegistryController.java | 2 +- .../controller/ResourceController.java | 24 +++++---- .../datasource/entity/ApplicationEntity.java | 6 +-- .../datasource/entity/MachineEntity.java | 2 +- .../sentinel/dashboard/discovery/AppInfo.java | 53 +++++++------------ .../dashboard/discovery/AppManagement.java | 8 +-- .../dashboard/discovery/MachineDiscovery.java | 19 ++++++- .../dashboard/discovery/MachineInfo.java | 16 +++--- .../discovery/SimpleMachineDiscovery.java | 14 +++-- .../dashboard/domain/vo/MachineInfoVo.java | 2 +- .../dashboard/rule/FlowRuleApiProvider.java | 12 +---- .../sentinel/dashboard/util/MachineUtils.java | 3 ++ .../app/scripts/controllers/authority.js | 2 +- .../app/scripts/controllers/cluster_single.js | 2 +- .../app/scripts/controllers/degrade.js | 2 +- .../app/scripts/controllers/flow_v1.js | 2 +- .../app/scripts/controllers/flow_v2.js | 2 +- .../app/scripts/controllers/identity.js | 5 +- .../app/scripts/controllers/param_flow.js | 2 +- .../app/scripts/controllers/system.js | 2 +- .../dashboard/discovery/AppInfoTest.java | 18 +++---- .../dashboard/discovery/MachineInfoTest.java | 14 +++-- .../metric/InMemoryMetricsRepositoryTest.java | 23 +++++--- .../dashboard/rule/apollo/ApolloConfig.java | 12 ++--- .../rule/apollo/FlowRuleApolloProvider.java | 15 +++--- .../rule/apollo/FlowRuleApolloPublisher.java | 20 +++---- 30 files changed, 193 insertions(+), 183 deletions(-) diff --git a/sentinel-dashboard/Sentinel_Dashboard_Feature.md b/sentinel-dashboard/Sentinel_Dashboard_Feature.md index 6a5efe0d..8c0529a8 100755 --- a/sentinel-dashboard/Sentinel_Dashboard_Feature.md +++ b/sentinel-dashboard/Sentinel_Dashboard_Feature.md @@ -49,8 +49,9 @@ Sentinel 提供了多种规则来保护系统的不同部分。流量控制规 ## 3. 配置项 -控制台的一些特性可以通过配置项来进行配置,配置项主要有两个来源:`System.getProperty()`和`System.getenv()`,同时存在时后者可以覆盖前者。 -> 环境变量因为不支持`.`所以需要将其更换为`_`。 +控制台的一些特性可以通过配置项来进行配置,配置项主要有两个来源:`System.getProperty()` 和 `System.getenv()`,同时存在时后者可以覆盖前者。 + +> 通过环境变量进行配置时,因为不支持 `.` 所以需要将其更换为 `_`。 项 | 类型 | 默认值 | 最小值 | 描述 --- | --- | --- | --- | --- @@ -61,15 +62,20 @@ sentinel.dashboard.autoRemoveMachineMillis | Integer | 0 | 300000 | 距离最近 配置示例: -命令行 +- 命令行方式: + ```shell java -Dsentinel.dashboard.app.hideAppNoMachineMillis=60000 ``` -java + +- Java 方式: + ```java System.setProperty("sentinel.dashboard.app.hideAppNoMachineMillis", "60000"); ``` -环境变量 + +- 环境变量方式: + ```shell sentinel_dashboard_app_hideAppNoMachineMillis=60000 ``` @@ -77,5 +83,4 @@ sentinel_dashboard_app_hideAppNoMachineMillis=60000 更多: - [Sentinel 控制台启动和客户端接入](./README.md) -- [控制台 Wiki](https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0) - +- [控制台 Wiki](https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0) \ No newline at end of file diff --git a/sentinel-dashboard/pom.xml b/sentinel-dashboard/pom.xml index 62d8cf2f..a3e8973a 100755 --- a/sentinel-dashboard/pom.xml +++ b/sentinel-dashboard/pom.xml @@ -16,7 +16,6 @@ 1.8 1.8 2.0.5.RELEASE - 1.2.0 @@ -39,12 +38,6 @@ ${project.version} - - com.alibaba.csp - sentinel-datasource-nacos - test - - org.springframework.boot spring-boot-starter-web @@ -99,6 +92,20 @@ fastjson + + + com.alibaba.csp + sentinel-datasource-nacos + test + + + + com.ctrip.framework.apollo + apollo-openapi + 1.2.0 + test + + junit junit @@ -109,13 +116,6 @@ mockito-core test - - - com.ctrip.framework.apollo - apollo-openapi - ${apollo.openapi.version} - test - com.github.stefanbirkner system-rules diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java index b1759006..21853829 100644 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java @@ -34,22 +34,26 @@ import org.springframework.lang.NonNull; * */ public class DashboardConfig { + + public static final int DEFAULT_MACHINE_HEALTHY_TIMEOUT_MS = 60_000; + /** - * hide app in sidebar when it had no healthy machine after specific period in millis + * Hide application name in sidebar when it has no healthy machines after specific period in millisecond. */ public static final String CONFIG_HIDE_APP_NO_MACHINE_MILLIS = "sentinel.dashboard.app.hideAppNoMachineMillis"; /** - * remove app when it had no healthy machine after specific period in millis + * Remove application when it has no healthy machines after specific period in millisecond. */ public static final String CONFIG_REMOVE_APP_NO_MACHINE_MILLIS = "sentinel.dashboard.removeAppNoMachineMillis"; /** - * unhealthy millis + * Timeout */ public static final String CONFIG_UNHEALTHY_MACHINE_MILLIS = "sentinel.dashboard.unhealthyMachineMillis"; /** - * auto remove unhealthy machine after specific period in millis + * Auto remove unhealthy machine after specific period in millisecond. */ public static final String CONFIG_AUTO_REMOVE_MACHINE_MILLIS = "sentinel.dashboard.autoRemoveMachineMillis"; + private static final ConcurrentMap cacheMap = new ConcurrentHashMap<>(); @NonNull @@ -94,7 +98,7 @@ public class DashboardConfig { } public static int getUnhealthyMachineMillis() { - return getConfigInt(CONFIG_UNHEALTHY_MACHINE_MILLIS, 60000, 30000); + return getConfigInt(CONFIG_UNHEALTHY_MACHINE_MILLIS, DEFAULT_MACHINE_HEALTHY_TIMEOUT_MS, 30000); } public static void clearCache() { diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java index b90db2d5..b892809c 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java @@ -28,40 +28,36 @@ import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; import com.alibaba.csp.sentinel.dashboard.domain.Result; import com.alibaba.csp.sentinel.dashboard.domain.vo.MachineInfoVo; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; /** - * 这个Controller负责app,机器信息的交互. + * @author Carpenter Lee */ -@Controller -@RequestMapping(value = "/app", produces = MediaType.APPLICATION_JSON_VALUE) +@RestController +@RequestMapping(value = "/app") public class AppController { @Autowired - AppManagement appManagement; + private AppManagement appManagement; - @ResponseBody - @RequestMapping("/names.json") - Result> queryApps(HttpServletRequest request) { + @GetMapping("/names.json") + public Result> queryApps(HttpServletRequest request) { return Result.ofSuccess(appManagement.getAppNames()); } - @ResponseBody - @RequestMapping("/briefinfos.json") - Result> queryAppInfos(HttpServletRequest request) { + @GetMapping("/briefinfos.json") + public Result> queryAppInfos(HttpServletRequest request) { List list = new ArrayList<>(appManagement.getBriefApps()); Collections.sort(list, Comparator.comparing(AppInfo::getApp)); return Result.ofSuccess(list); } - @ResponseBody - @RequestMapping(value = "/{app}/machines.json") - Result> getMachinesByApp(@PathVariable("app") String app) { + @GetMapping(value = "/{app}/machines.json") + public Result> getMachinesByApp(@PathVariable("app") String app) { AppInfo appInfo = appManagement.getDetailApp(app); if (appInfo == null) { return Result.ofSuccess(null); @@ -81,9 +77,8 @@ public class AppController { return Result.ofSuccess(MachineInfoVo.fromMachineInfoList(list)); } - @ResponseBody - @RequestMapping(value = "/{app}/machine/remove.json") - Result removeMachineById( + @GetMapping(value = "/{app}/machine/remove.json") + public Result removeMachineById( @PathVariable("app") String app, @RequestParam(name = "ip") String ip, @RequestParam(name = "port") int port) { diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java index 8610e40c..f2e7fe2a 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java @@ -63,7 +63,7 @@ public class MachineRegistryController { machineInfo.setIp(ip); machineInfo.setPort(port); machineInfo.setHeartbeatVersion(version); - machineInfo.setLastHeatbeat(System.currentTimeMillis()); + machineInfo.setLastHeartbeat(System.currentTimeMillis()); machineInfo.setVersion(sentinelVersion); appManagement.addMachine(machineInfo); return Result.ofSuccessMsg("success"); diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java index f1a9a9df..70382c7e 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java @@ -25,24 +25,25 @@ import com.alibaba.csp.sentinel.dashboard.domain.ResourceTreeNode; import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; import com.alibaba.csp.sentinel.dashboard.domain.Result; import com.alibaba.csp.sentinel.dashboard.domain.vo.ResourceVo; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; /** - * @author leyou + * @author Carpenter Lee */ -@Controller -@RequestMapping(value = "/resource", produces = MediaType.APPLICATION_JSON_VALUE) +@RestController +@RequestMapping(value = "/resource") public class ResourceController { private static Logger logger = LoggerFactory.getLogger(ResourceController.class); + @Autowired - SentinelApiClient httpFetcher; + private SentinelApiClient httpFetcher; /** * Fetch real time statistics info of the machine. @@ -54,9 +55,9 @@ public class ResourceController { * @param searchKey key to search * @return node statistics info. */ - @ResponseBody - @RequestMapping("/machineResource.json") - Result fetchIdentityOfMachine(String ip, Integer port, String type, String searchKey) { + @GetMapping("/machineResource.json") + public Result> fetchResourceChainListOfMachine(String ip, Integer port, String type, + String searchKey) { if (StringUtil.isEmpty(ip) || port == null) { return Result.ofFail(-1, "invalid param, give ip, port"); } @@ -73,7 +74,8 @@ public class ResourceController { ResourceTreeNode treeNode = ResourceTreeNode.fromNodeVoList(nodeVos); treeNode.searchIgnoreCase(searchKey); return Result.ofSuccess(ResourceVo.fromResourceTreeNode(treeNode)); - } else {// cluster + } else { + // Normal (cluster node). List nodeVos = httpFetcher.fetchClusterNodeOfMachine(ip, port, true); if (nodeVos == null) { return Result.ofSuccess(null); diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java index edaee180..51dc229e 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java @@ -23,6 +23,7 @@ import com.alibaba.csp.sentinel.dashboard.discovery.AppInfo; * @author leyou */ public class ApplicationEntity { + private Long id; private Date gmtCreate; private Date gmtModified; @@ -79,10 +80,7 @@ public class ApplicationEntity { } public AppInfo toAppInfo() { - AppInfo appInfo = new AppInfo(); - appInfo.setApp(app); - - return appInfo; + return new AppInfo(app); } @Override diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java index c1088dee..5b91f339 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java @@ -103,7 +103,7 @@ public class MachineEntity { machineInfo.setHostname(hostname); machineInfo.setIp(ip); machineInfo.setPort(port); - machineInfo.setLastHeatbeat(timestamp.getTime()); + machineInfo.setLastHeartbeat(timestamp.getTime()); machineInfo.setHeartbeatVersion(timestamp.getTime()); return machineInfo; diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java index 98aeefb3..01d3183f 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java @@ -25,26 +25,12 @@ import java.util.concurrent.ConcurrentHashMap; import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig; public class AppInfo { - private static final Comparator COMPARATOR_BY_MACHINE_HEARTBEAT_DESC = new Comparator() { - - @Override - public int compare(MachineInfo o1, MachineInfo o2) { - if (o1.getLastHeatbeat() < o2.getLastHeatbeat()) { - return -1; - } - if (o1.getLastHeatbeat() > o2.getLastHeatbeat()) { - return 1; - } - return 0; - } - }; private String app = ""; private Set machines = ConcurrentHashMap.newKeySet(); - public AppInfo() { - } + public AppInfo() {} public AppInfo(String app) { this.app = app; @@ -76,7 +62,7 @@ public class AppInfo { machines.remove(machineInfo); return machines.add(machineInfo); } - + public synchronized boolean removeMachine(String ip, int port) { Iterator it = machines.iterator(); while (it.hasNext()) { @@ -88,44 +74,45 @@ public class AppInfo { } return false; } - + public Optional getMachine(String ip, int port) { return machines.stream() .filter(e -> e.getIp().equals(ip) && e.getPort().equals(port)) .findFirst(); } - - private boolean heartbeatJudge(int threshold) { + + private boolean heartbeatJudge(final int threshold) { if (machines.size() == 0) { return false; } if (threshold > 0) { long healthyCount = machines.stream() - .filter(m -> m.isHealthy()) - .count(); + .filter(MachineInfo::isHealthy) + .count(); if (healthyCount == 0) { - // no machine - long recentHeartBeat = machines.stream() - .max(COMPARATOR_BY_MACHINE_HEARTBEAT_DESC).get().getLastHeatbeat(); - return System.currentTimeMillis() - recentHeartBeat < threshold; + // No healthy machines. + return machines.stream() + .max(Comparator.comparingLong(MachineInfo::getLastHeartbeat)) + .map(e -> System.currentTimeMillis() - e.getLastHeartbeat() < threshold) + .orElse(false); } } return true; } - + /** - * having no healthy machine and should not be displayed - * - * @return + * Check whether current application has no healthy machines and should not be displayed. + * + * @return true if the application should be displayed in the sidebar, otherwise false */ public boolean isShown() { return heartbeatJudge(DashboardConfig.getHideAppNoMachineMillis()); } - + /** - * having no healthy machine and should be removed - * - * @return + * Check whether current application has no healthy machines and should be removed. + * + * @return true if the application is dead and should be removed, otherwise false */ public boolean isDead() { return !heartbeatJudge(DashboardConfig.getRemoveAppNoMachineMillis()); diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java index c158dcdc..9e44336f 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java @@ -27,16 +27,10 @@ import org.springframework.stereotype.Component; @Component public class AppManagement implements MachineDiscovery { - //@Value("${appmanagement.maxnode}") - //private Integer maxNode; - // - //@Value("${discovery.type}") - //private String type; - @Autowired private ApplicationContext context; - MachineDiscovery machineDiscovery; + private MachineDiscovery machineDiscovery; @PostConstruct public void init() { diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java index 635c7b60..260b0d8c 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java @@ -27,10 +27,25 @@ public interface MachineDiscovery { Set getBriefApps(); AppInfo getDetailApp(String app); - + + /** + * Remove the given app from the application registry. + * + * @param app application name + * @since 1.5.0 + */ void removeApp(String app); long addMachine(MachineInfo machineInfo); - + + /** + * Remove the given machine instance from the application registry. + * + * @param app the application name of the machine + * @param ip machine IP + * @param port machine port + * @return true if removed, otherwise false + * @since 1.5.0 + */ boolean removeMachine(String app, String ip, int port); } \ No newline at end of file diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java index 10db4377..9c65f365 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java @@ -26,7 +26,7 @@ public class MachineInfo implements Comparable { private String hostname = ""; private String ip = ""; private Integer port = -1; - private long lastHeatbeat; + private long lastHeartbeat; private long heartbeatVersion; /** @@ -96,7 +96,7 @@ public class MachineInfo implements Comparable { } public boolean isHealthy() { - long delta = System.currentTimeMillis() - lastHeatbeat; + long delta = System.currentTimeMillis() - lastHeartbeat; return delta < DashboardConfig.getUnhealthyMachineMillis(); } @@ -107,18 +107,18 @@ public class MachineInfo implements Comparable { */ public boolean isDead() { if (DashboardConfig.getAutoRemoveMachineMillis() > 0) { - long delta = System.currentTimeMillis() - lastHeatbeat; + long delta = System.currentTimeMillis() - lastHeartbeat; return delta > DashboardConfig.getAutoRemoveMachineMillis(); } return false; } - public long getLastHeatbeat() { - return lastHeatbeat; + public long getLastHeartbeat() { + return lastHeartbeat; } - public void setLastHeatbeat(long lastHeatbeat) { - this.lastHeatbeat = lastHeatbeat; + public void setLastHeartbeat(long lastHeartbeat) { + this.lastHeartbeat = lastHeartbeat; } @Override @@ -143,7 +143,7 @@ public class MachineInfo implements Comparable { .append(", ip='").append(ip).append('\'') .append(", port=").append(port) .append(", heartbeatVersion=").append(heartbeatVersion) - .append(", lastHeartbeat=").append(lastHeatbeat) + .append(", lastHeartbeat=").append(lastHeartbeat) .append(", version='").append(version).append('\'') .append(", healthy=").append(isHealthy()) .append('}').toString(); diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java index e6751074..23ce943d 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java @@ -20,6 +20,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import com.alibaba.csp.sentinel.util.AssertUtil; import org.springframework.stereotype.Component; @@ -28,17 +31,20 @@ import org.springframework.stereotype.Component; */ @Component public class SimpleMachineDiscovery implements MachineDiscovery { - protected ConcurrentHashMap apps = new ConcurrentHashMap<>(); + + private final ConcurrentMap apps = new ConcurrentHashMap<>(); @Override public long addMachine(MachineInfo machineInfo) { - AppInfo appInfo = apps.computeIfAbsent(machineInfo.getApp(), app -> new AppInfo(app)); + AssertUtil.notNull(machineInfo, "machineInfo cannot be null"); + AppInfo appInfo = apps.computeIfAbsent(machineInfo.getApp(), AppInfo::new); appInfo.addMachine(machineInfo); return 1; } - + @Override public boolean removeMachine(String app, String ip, int port) { + AssertUtil.assertNotBlank(app, "app name cannot be blank"); AppInfo appInfo = apps.get(app); if (appInfo != null) { return appInfo.removeMachine(ip, port); @@ -53,6 +59,7 @@ public class SimpleMachineDiscovery implements MachineDiscovery { @Override public AppInfo getDetailApp(String app) { + AssertUtil.assertNotBlank(app, "app name cannot be blank"); return apps.get(app); } @@ -63,6 +70,7 @@ public class SimpleMachineDiscovery implements MachineDiscovery { @Override public void removeApp(String app) { + AssertUtil.assertNotBlank(app, "app name cannot be blank"); apps.remove(app); } diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/vo/MachineInfoVo.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/vo/MachineInfoVo.java index 41c400fb..66428c14 100755 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/vo/MachineInfoVo.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/vo/MachineInfoVo.java @@ -49,7 +49,7 @@ public class MachineInfoVo { vo.setHostname(machine.getHostname()); vo.setIp(machine.getIp()); vo.setPort(machine.getPort()); - vo.setLastHeartbeat(machine.getLastHeatbeat()); + vo.setLastHeartbeat(machine.getLastHeartbeat()); vo.setHeartbeatVersion(machine.getHeartbeatVersion()); vo.setVersion(machine.getVersion()); vo.setHealthy(machine.isHealthy()); diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleApiProvider.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleApiProvider.java index 632bc8a8..9f9ce5cc 100644 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleApiProvider.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleApiProvider.java @@ -47,16 +47,8 @@ public class FlowRuleApiProvider implements DynamicRuleProvider list = appManagement.getDetailApp(appName).getMachines() .stream() - .filter(e -> e.isHealthy()) - .sorted((e1, e2) -> { - if (e1.getLastHeatbeat() < e2.getLastHeatbeat()) { - return 1; - } else if (e1.getLastHeatbeat() > e2.getLastHeatbeat()) { - return -1; - } else { - return 0; - } - }).collect(Collectors.toList()); + .filter(MachineInfo::isHealthy) + .sorted((e1, e2) -> Long.compare(e2.getLastHeartbeat(), e1.getLastHeartbeat())).collect(Collectors.toList()); if (list.isEmpty()) { return new ArrayList<>(); } else { diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/util/MachineUtils.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/util/MachineUtils.java index 9020435c..5b3073cf 100644 --- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/util/MachineUtils.java +++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/util/MachineUtils.java @@ -24,6 +24,7 @@ import com.alibaba.csp.sentinel.util.function.Tuple2; * @author Eric Zhao */ public final class MachineUtils { + public static Optional parseCommandPort(String machineIp) { try { if (!machineIp.contains("@")) { @@ -53,4 +54,6 @@ public final class MachineUtils { return Optional.empty(); } } + + private MachineUtils() {} } diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js index fb7b789d..3d86302f 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js @@ -202,7 +202,7 @@ angular.module('sentinelDashboardApp').controller('AuthorityRuleController', ['$ $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/cluster_single.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/cluster_single.js index ffdbe637..7392229d 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/cluster_single.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/cluster_single.js @@ -217,7 +217,7 @@ app.controller('SentinelClusterSingleController', ['$scope', '$stateParams', 'ng $scope.macsInputOptionsOrigin = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptionsOrigin.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js index 45773c66..8a05323e 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js @@ -177,7 +177,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v1.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v1.js index 643ff12d..8e4be2ab 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v1.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v1.js @@ -195,7 +195,7 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', ' $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v2.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v2.js index 8a98c8d5..3280675b 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v2.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_v2.js @@ -196,7 +196,7 @@ app.controller('FlowControllerV2', ['$scope', '$stateParams', 'FlowServiceV2', ' $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js index 2b09ffd4..33a4ec07 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js @@ -387,13 +387,12 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', function queryAppMachines() { MachineService.getAppMachines($scope.app).success( function (data) { - if (data.code == 0) { - // $scope.machines = data.data; + if (data.code === 0) { if (data.data) { $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js index 65cf157e..03a2054f 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js @@ -294,7 +294,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/system.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/system.js index 8e7ed655..ff754727 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/system.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/system.js @@ -205,7 +205,7 @@ app.controller('SystemCtl', ['$scope', '$stateParams', 'SystemService', 'ngDialo $scope.machines = []; $scope.macsInputOptions = []; data.data.forEach(function (item) { - if (item.health) { + if (item.healthy) { $scope.macsInputOptions.push({ text: item.ip + ':' + item.port, value: item.ip + ':' + item.port diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfoTest.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfoTest.java index 8ed510c9..b8fcacb1 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfoTest.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfoTest.java @@ -79,7 +79,7 @@ public class AppInfoTest { machineInfo.setHostname("bogon"); machineInfo.setIp("127.0.0.1"); machineInfo.setPort(3389); - machineInfo.setLastHeatbeat(System.currentTimeMillis()); + machineInfo.setLastHeartbeat(System.currentTimeMillis()); machineInfo.setHeartbeatVersion(1); machineInfo.setVersion("0.4.1"); appInfo.addMachine(machineInfo); @@ -92,7 +92,7 @@ public class AppInfoTest { machineInfo.setHostname("bogon"); machineInfo.setIp("127.0.0.1"); machineInfo.setPort(3389); - machineInfo.setLastHeatbeat(System.currentTimeMillis()); + machineInfo.setLastHeartbeat(System.currentTimeMillis()); machineInfo.setHeartbeatVersion(1); machineInfo.setVersion("0.4.2"); appInfo.addMachine(machineInfo); @@ -105,7 +105,7 @@ public class AppInfoTest { machineInfo.setHostname("bogon"); machineInfo.setIp("127.0.0.1"); machineInfo.setPort(3390); - machineInfo.setLastHeatbeat(System.currentTimeMillis()); + machineInfo.setLastHeartbeat(System.currentTimeMillis()); machineInfo.setHeartbeatVersion(1); machineInfo.setVersion("0.4.3"); appInfo.addMachine(machineInfo); @@ -116,7 +116,7 @@ public class AppInfoTest { appInfo.removeMachine("127.0.0.1", 3390); assertEquals(0, appInfo.getMachines().size()); } - + @Test public void testHealthyAndDead() { System.setProperty(DashboardConfig.CONFIG_HIDE_APP_NO_MACHINE_MILLIS, "60000"); @@ -128,25 +128,25 @@ public class AppInfoTest { { MachineInfo machineInfo = MachineInfo.of(appName, "127.0.0.1", 8801); machineInfo.setHeartbeatVersion(1); - machineInfo.setLastHeatbeat(System.currentTimeMillis()); + machineInfo.setLastHeartbeat(System.currentTimeMillis()); appInfo.addMachine(machineInfo); } assertTrue(appInfo.isShown()); assertFalse(appInfo.isDead()); - + { MachineInfo machineInfo = MachineInfo.of(appName, "127.0.0.1", 8801); machineInfo.setHeartbeatVersion(1); - machineInfo.setLastHeatbeat(System.currentTimeMillis() - 70000); + machineInfo.setLastHeartbeat(System.currentTimeMillis() - 70000); appInfo.addMachine(machineInfo); } assertFalse(appInfo.isShown()); assertFalse(appInfo.isDead()); - + { MachineInfo machineInfo = MachineInfo.of(appName, "127.0.0.1", 8801); machineInfo.setHeartbeatVersion(1); - machineInfo.setLastHeatbeat(System.currentTimeMillis() - 700000); + machineInfo.setLastHeartbeat(System.currentTimeMillis() - 700000); appInfo.addMachine(machineInfo); } assertFalse(appInfo.isShown()); diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfoTest.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfoTest.java index 879823bb..bb526b9e 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfoTest.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfoTest.java @@ -21,7 +21,11 @@ import org.junit.Test; import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig; +/** + * @author Jason Joo + */ public class MachineInfoTest { + @Test public void testHealthyAndDead() { System.setProperty(DashboardConfig.CONFIG_UNHEALTHY_MACHINE_MILLIS, "60000"); @@ -29,15 +33,15 @@ public class MachineInfoTest { DashboardConfig.clearCache(); MachineInfo machineInfo = new MachineInfo(); machineInfo.setHeartbeatVersion(1); - machineInfo.setLastHeatbeat(System.currentTimeMillis() - 10000); + machineInfo.setLastHeartbeat(System.currentTimeMillis() - 10000); assertTrue(machineInfo.isHealthy()); assertFalse(machineInfo.isDead()); - - machineInfo.setLastHeatbeat(System.currentTimeMillis() - 100000); + + machineInfo.setLastHeartbeat(System.currentTimeMillis() - 100000); assertFalse(machineInfo.isHealthy()); assertFalse(machineInfo.isDead()); - - machineInfo.setLastHeatbeat(System.currentTimeMillis() - 1000000); + + machineInfo.setLastHeartbeat(System.currentTimeMillis() - 1000000); assertFalse(machineInfo.isHealthy()); assertTrue(machineInfo.isDead()); } diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/repository/metric/InMemoryMetricsRepositoryTest.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/repository/metric/InMemoryMetricsRepositoryTest.java index c4a11d7b..17f81970 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/repository/metric/InMemoryMetricsRepositoryTest.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/repository/metric/InMemoryMetricsRepositoryTest.java @@ -119,13 +119,11 @@ public class InMemoryMetricsRepositoryTest { try { cyclicBarrier.await(); inMemoryMetricsRepository.listResourcesOfApp(DEFAULT_APP); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (BrokenBarrierException e) { + } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } - }, executorService - )); + }, executorService) + ); } // batch add metric entity @@ -142,11 +140,20 @@ public class InMemoryMetricsRepositoryTest { } CompletableFuture all = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + try { - all.join(); - } catch (ConcurrentModificationException e) { + all.get(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { e.printStackTrace(); - fail("concurrent error occurred"); + } catch (ExecutionException e) { + e.getCause().printStackTrace(); + if (e.getCause() instanceof ConcurrentModificationException) { + fail("concurrent error occurred"); + } else { + fail("unexpected exception"); + } + } catch (TimeoutException e) { + fail("allOf future timeout"); } } diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/ApolloConfig.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/ApolloConfig.java index a35c6f70..57ecae75 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/ApolloConfig.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/ApolloConfig.java @@ -19,11 +19,11 @@ import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; + import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.fastjson.JSON; -import com.alibaba.nacos.api.config.ConfigFactory; -import com.alibaba.nacos.api.config.ConfigService; + import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient; /** @@ -44,11 +44,11 @@ public class ApolloConfig { } @Bean - public ApolloOpenApiClient apolloOpenApiClient(){ + public ApolloOpenApiClient apolloOpenApiClient() { ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder() - .withPortalUrl("http://localhost:10034") - .withToken("token") - .build(); + .withPortalUrl("http://localhost:10034") + .withToken("token") + .build(); return client; } diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloProvider.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloProvider.java index 9baf12fe..0f55d817 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloProvider.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloProvider.java @@ -20,10 +20,12 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; + import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.util.StringUtil; + import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO; @@ -46,17 +48,16 @@ public class FlowRuleApolloProvider implements DynamicRuleProvider p.getKey().equals(flowDataId)) - .map(OpenItemDTO::getValue) - .findFirst() - .orElse(""); + .getItems() + .stream() + .filter(p -> p.getKey().equals(flowDataId)) + .map(OpenItemDTO::getValue) + .findFirst() + .orElse(""); if (StringUtil.isEmpty(rules)) { return new ArrayList<>(); } return converter.convert(rules); - } } diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloPublisher.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloPublisher.java index bb7fdbb6..05bef96b 100644 --- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloPublisher.java +++ b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/apollo/FlowRuleApolloPublisher.java @@ -19,11 +19,12 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; + import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.util.AssertUtil; -import com.alibaba.nacos.api.config.ConfigService; + import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient; import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; @@ -47,27 +48,22 @@ public class FlowRuleApolloPublisher implements DynamicRulePublisher