Skip to content

Commit

Permalink
dashboard: Improve error handling in FlowController and update sample…
Browse files Browse the repository at this point in the history
… WebConfig

Signed-off-by: Eric Zhao <[email protected]>
  • Loading branch information
sczyh30 committed Dec 23, 2019
1 parent 0e110c6 commit a5d6773
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -365,17 +365,44 @@ private boolean setRules(String app, String ip, int port, String type, List<? ex
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);
}
Expand Down Expand Up @@ -487,6 +514,10 @@ public boolean setFlowRuleOfMachine(String app, String ip, int port, List<FlowRu
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -75,6 +79,9 @@ public FilterRegistrationBean sentinelFilterRegistration() {
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");

Expand All @@ -83,12 +90,14 @@ public FilterRegistrationBean sentinelFilterRegistration() {

@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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

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;
Expand Down Expand Up @@ -145,19 +148,19 @@ public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity)
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);
}
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
logger.error("Publish flow rules failed after rule add");

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());
}
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,
Expand Down Expand Up @@ -222,21 +225,22 @@ public Result<FlowRuleEntity> updateIfNotNull(Long id, String app,
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);
}
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
logger.info("publish flow rules fail after rule update");

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());
}
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");
Expand All @@ -251,14 +255,19 @@ public Result<Long> delete(Long id) {
} 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});
};
Expand All @@ -173,15 +173,15 @@ 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();
} else {
confirmDialog.close();
}
} else {
alert('失败!');
alert('失败:' + data.msg);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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('未知错误');
Expand All @@ -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);
}
});
}
Expand Down Expand Up @@ -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);
}
});
}
Expand All @@ -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);
}
});
}
Expand Down

0 comments on commit a5d6773

Please sign in to comment.