dashboard: Improve error handling in FlowController and update sample WebConfig
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
0e110c68ea
commit
a5d6773cbc
|
|
@ -365,17 +365,44 @@ public class SentinelApiClient {
|
|||
params.put("type", type);
|
||||
params.put("data", data);
|
||||
String result = executeCommand(app, ip, port, SET_RULES_PATH, params, true).get();
|
||||
logger.info("setRules: {}", result);
|
||||
logger.info("setRules result: {}, type={}", result, type);
|
||||
return true;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
logger.warn("setRules api failed: {}", type, e);
|
||||
} catch (InterruptedException e) {
|
||||
logger.warn("setRules API failed: {}", type, e);
|
||||
return false;
|
||||
} catch (ExecutionException e) {
|
||||
logger.warn("setRules API failed: {}", type, e.getCause());
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
logger.warn("setRules failed", e);
|
||||
logger.error("setRules API failed, type={}", type, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> setRulesAsync(String app, String ip, int port, String type, List<? extends RuleEntity> entities) {
|
||||
try {
|
||||
AssertUtil.notNull(entities, "rules cannot be null");
|
||||
AssertUtil.notEmpty(app, "Bad app name");
|
||||
AssertUtil.notEmpty(ip, "Bad machine IP");
|
||||
AssertUtil.isTrue(port > 0, "Bad machine port");
|
||||
String data = JSON.toJSONString(
|
||||
entities.stream().map(r -> r.toRule()).collect(Collectors.toList()));
|
||||
Map<String, String> params = new HashMap<>(2);
|
||||
params.put("type", type);
|
||||
params.put("data", data);
|
||||
return executeCommand(app, ip, port, SET_RULES_PATH, params, true)
|
||||
.thenCompose(r -> {
|
||||
if ("success".equalsIgnoreCase(r.trim())) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
return AsyncUtils.newFailedFuture(new CommandFailedException(r));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("setRulesAsync API failed, type={}", type, e);
|
||||
return AsyncUtils.newFailedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<NodeVo> fetchResourceOfMachine(String ip, int port, String type) {
|
||||
return fetchItems(ip, port, RESOURCE_URL_PATH, type, NodeVo.class);
|
||||
}
|
||||
|
|
@ -487,6 +514,10 @@ public class SentinelApiClient {
|
|||
return setRules(app, ip, port, FLOW_RULE_TYPE, rules);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> setFlowRuleOfMachineAsync(String app, String ip, int port, List<FlowRuleEntity> rules) {
|
||||
return setRulesAsync(app, ip, port, FLOW_RULE_TYPE, rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* set rules of the machine. rules == null will return immediately;
|
||||
* rules.isEmpty() means setting the rules to empty.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
package com.alibaba.csp.sentinel.dashboard.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
|
||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor;
|
||||
|
|
@ -75,6 +79,9 @@ public class WebConfig implements WebMvcConfigurer {
|
|||
registration.addUrlPatterns("/*");
|
||||
registration.setName("sentinelFilter");
|
||||
registration.setOrder(1);
|
||||
// If this is enabled, the entrance of all Web URL resources will be unified as a single context name.
|
||||
// In most scenarios that's enough, and it could reduce the memory footprint.
|
||||
registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "true");
|
||||
|
||||
logger.info("Sentinel servlet CommonFilter registered");
|
||||
|
||||
|
|
@ -83,12 +90,14 @@ public class WebConfig implements WebMvcConfigurer {
|
|||
|
||||
@PostConstruct
|
||||
public void doInit() {
|
||||
Set<String> suffixSet = new HashSet<>(Arrays.asList(".js", ".css", ".html", ".ico", ".txt",
|
||||
".woff", ".woff2"));
|
||||
// Example: register a UrlCleaner to exclude URLs of common static resources.
|
||||
WebCallbackManager.setUrlCleaner(url -> {
|
||||
if (StringUtil.isEmpty(url)) {
|
||||
return url;
|
||||
}
|
||||
if (url.endsWith(".js") || url.endsWith(".css") || url.endsWith("html")) {
|
||||
if (suffixSet.stream().anyMatch(url::endsWith)) {
|
||||
return null;
|
||||
}
|
||||
return url;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ package com.alibaba.csp.sentinel.dashboard.controller;
|
|||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
|
||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
|
||||
|
|
@ -145,19 +148,19 @@ public class FlowControllerV1 {
|
|||
entity.setResource(entity.getResource().trim());
|
||||
try {
|
||||
entity = repository.save(entity);
|
||||
} catch (Throwable throwable) {
|
||||
logger.error("Failed to add flow rule", throwable);
|
||||
return Result.ofThrowable(-1, throwable);
|
||||
|
||||
publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
|
||||
return Result.ofSuccess(entity);
|
||||
} catch (Throwable t) {
|
||||
Throwable e = t instanceof ExecutionException ? t.getCause() : t;
|
||||
logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
|
||||
return Result.ofFail(-1, e.getMessage());
|
||||
}
|
||||
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
|
||||
logger.error("Publish flow rules failed after rule add");
|
||||
}
|
||||
return Result.ofSuccess(entity);
|
||||
}
|
||||
|
||||
@PutMapping("/save.json")
|
||||
@AuthAction(PrivilegeType.WRITE_RULE)
|
||||
public Result<FlowRuleEntity> updateIfNotNull(Long id, String app,
|
||||
public Result<FlowRuleEntity> apiUpdateFlowRule(Long id, String app,
|
||||
String limitApp, String resource, Integer grade,
|
||||
Double count, Integer strategy, String refResource,
|
||||
Integer controlBehavior, Integer warmUpPeriodSec,
|
||||
|
|
@ -222,21 +225,22 @@ public class FlowControllerV1 {
|
|||
try {
|
||||
entity = repository.save(entity);
|
||||
if (entity == null) {
|
||||
return Result.ofFail(-1, "save entity fail");
|
||||
return Result.ofFail(-1, "save entity fail: null");
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
logger.error("save error:", throwable);
|
||||
return Result.ofThrowable(-1, throwable);
|
||||
|
||||
publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
|
||||
return Result.ofSuccess(entity);
|
||||
} catch (Throwable t) {
|
||||
Throwable e = t instanceof ExecutionException ? t.getCause() : t;
|
||||
logger.error("Error when updating flow rules, app={}, ip={}, ruleId={}", entity.getApp(),
|
||||
entity.getIp(), id, e);
|
||||
return Result.ofFail(-1, e.getMessage());
|
||||
}
|
||||
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
|
||||
logger.info("publish flow rules fail after rule update");
|
||||
}
|
||||
return Result.ofSuccess(entity);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete.json")
|
||||
@AuthAction(PrivilegeType.WRITE_RULE)
|
||||
public Result<Long> delete(Long id) {
|
||||
public Result<Long> apiDeleteFlowRule(Long id) {
|
||||
|
||||
if (id == null) {
|
||||
return Result.ofFail(-1, "id can't be null");
|
||||
|
|
@ -251,14 +255,19 @@ public class FlowControllerV1 {
|
|||
} catch (Exception e) {
|
||||
return Result.ofFail(-1, e.getMessage());
|
||||
}
|
||||
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
|
||||
logger.info("publish flow rules fail after rule delete");
|
||||
try {
|
||||
publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);
|
||||
return Result.ofSuccess(id);
|
||||
} catch (Throwable t) {
|
||||
Throwable e = t instanceof ExecutionException ? t.getCause() : t;
|
||||
logger.error("Error when deleting flow rules, app={}, ip={}, id={}", oldEntity.getApp(),
|
||||
oldEntity.getIp(), id, e);
|
||||
return Result.ofFail(-1, e.getMessage());
|
||||
}
|
||||
return Result.ofSuccess(id);
|
||||
}
|
||||
|
||||
private boolean publishRules(String app, String ip, Integer port) {
|
||||
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
|
||||
List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
|
||||
return sentinelApiClient.setFlowRuleOfMachine(app, ip, port, rules);
|
||||
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,18 +148,18 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', '
|
|||
getMachineRules();
|
||||
confirmDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function addNewRule(rule) {
|
||||
FlowService.newRule(rule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
getMachineRules();
|
||||
flowRuleDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -173,7 +173,7 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', '
|
|||
|
||||
function saveRule(rule, edit) {
|
||||
FlowService.saveRule(rule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
getMachineRules();
|
||||
if (edit) {
|
||||
flowRuleDialog.close();
|
||||
|
|
@ -181,7 +181,7 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', '
|
|||
confirmDialog.close();
|
||||
}
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
let url = '/dashboard/flow/' + $scope.app;
|
||||
$location.path(url);
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
alert('未知错误');
|
||||
|
|
@ -110,10 +110,10 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
return;
|
||||
}
|
||||
FlowService.newRule(flowRuleDialogScope.currentRule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
flowRuleDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -159,12 +159,12 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
return;
|
||||
}
|
||||
DegradeService.newRule(degradeRuleDialogScope.currentRule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
degradeRuleDialog.close();
|
||||
var url = '/dashboard/degrade/' + $scope.app;
|
||||
$location.path(url);
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -174,10 +174,10 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
return;
|
||||
}
|
||||
DegradeService.newRule(degradeRuleDialogScope.currentRule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
degradeRuleDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
alert('失败:' + data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue