dashboard: Refactor degrade service/controller and adapt to new features
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
8643dac943
commit
5334f51d21
|
|
@ -22,40 +22,46 @@ import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
|
||||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
|
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
|
||||||
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
|
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
|
||||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
|
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
|
||||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||||
|
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
|
||||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
|
||||||
import com.alibaba.csp.sentinel.dashboard.domain.Result;
|
import com.alibaba.csp.sentinel.dashboard.domain.Result;
|
||||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
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.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author leyou
|
* Controller regarding APIs of degrade rules. Refactored since 1.8.0.
|
||||||
|
*
|
||||||
|
* @author Carpenter Lee
|
||||||
|
* @author Eric Zhao
|
||||||
*/
|
*/
|
||||||
@Controller
|
@RestController
|
||||||
@RequestMapping(value = "/degrade", produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping("/degrade")
|
||||||
public class DegradeController {
|
public class DegradeController {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(DegradeController.class);
|
private final Logger logger = LoggerFactory.getLogger(DegradeController.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private InMemDegradeRuleStore repository;
|
private RuleRepository<DegradeRuleEntity, Long> repository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SentinelApiClient sentinelApiClient;
|
private SentinelApiClient sentinelApiClient;
|
||||||
|
|
||||||
@ResponseBody
|
@GetMapping("/rules.json")
|
||||||
@RequestMapping("/rules.json")
|
|
||||||
@AuthAction(PrivilegeType.READ_RULE)
|
@AuthAction(PrivilegeType.READ_RULE)
|
||||||
public Result<List<DegradeRuleEntity>> queryMachineRules(String app, String ip, Integer port) {
|
public Result<List<DegradeRuleEntity>> apiQueryMachineRules(String app, String ip, Integer port) {
|
||||||
|
|
||||||
if (StringUtil.isEmpty(app)) {
|
if (StringUtil.isEmpty(app)) {
|
||||||
return Result.ofFail(-1, "app can't be null or empty");
|
return Result.ofFail(-1, "app can't be null or empty");
|
||||||
}
|
}
|
||||||
|
|
@ -75,117 +81,65 @@ public class DegradeController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResponseBody
|
@PostMapping("/rule")
|
||||||
@RequestMapping("/new.json")
|
|
||||||
@AuthAction(PrivilegeType.WRITE_RULE)
|
@AuthAction(PrivilegeType.WRITE_RULE)
|
||||||
public Result<DegradeRuleEntity> add(String app, String ip, Integer port, String limitApp, String resource,
|
public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) {
|
||||||
Double count, Integer timeWindow, Integer grade) {
|
Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
|
||||||
if (StringUtil.isBlank(app)) {
|
if (checkResult != null) {
|
||||||
return Result.ofFail(-1, "app can't be null or empty");
|
return checkResult;
|
||||||
}
|
}
|
||||||
if (StringUtil.isBlank(ip)) {
|
|
||||||
return Result.ofFail(-1, "ip can't be null or empty");
|
|
||||||
}
|
|
||||||
if (port == null) {
|
|
||||||
return Result.ofFail(-1, "port can't be null");
|
|
||||||
}
|
|
||||||
if (StringUtil.isBlank(limitApp)) {
|
|
||||||
return Result.ofFail(-1, "limitApp can't be null or empty");
|
|
||||||
}
|
|
||||||
if (StringUtil.isBlank(resource)) {
|
|
||||||
return Result.ofFail(-1, "resource can't be null or empty");
|
|
||||||
}
|
|
||||||
if (count == null) {
|
|
||||||
return Result.ofFail(-1, "count can't be null");
|
|
||||||
}
|
|
||||||
if (timeWindow == null) {
|
|
||||||
return Result.ofFail(-1, "timeWindow can't be null");
|
|
||||||
}
|
|
||||||
if (grade == null) {
|
|
||||||
return Result.ofFail(-1, "grade can't be null");
|
|
||||||
}
|
|
||||||
if (grade < RuleConstant.DEGRADE_GRADE_RT || grade > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
|
|
||||||
return Result.ofFail(-1, "Invalid grade: " + grade);
|
|
||||||
}
|
|
||||||
DegradeRuleEntity entity = new DegradeRuleEntity();
|
|
||||||
entity.setApp(app.trim());
|
|
||||||
entity.setIp(ip.trim());
|
|
||||||
entity.setPort(port);
|
|
||||||
entity.setLimitApp(limitApp.trim());
|
|
||||||
entity.setResource(resource.trim());
|
|
||||||
entity.setCount(count);
|
|
||||||
entity.setTimeWindow(timeWindow);
|
|
||||||
entity.setGrade(grade);
|
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
entity.setGmtCreate(date);
|
entity.setGmtCreate(date);
|
||||||
entity.setGmtModified(date);
|
entity.setGmtModified(date);
|
||||||
try {
|
try {
|
||||||
entity = repository.save(entity);
|
entity = repository.save(entity);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable t) {
|
||||||
logger.error("add error:", throwable);
|
logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
|
||||||
return Result.ofThrowable(-1, throwable);
|
return Result.ofThrowable(-1, t);
|
||||||
}
|
|
||||||
if (!publishRules(app, ip, port)) {
|
|
||||||
logger.info("publish degrade rules fail after rule add");
|
|
||||||
}
|
|
||||||
return Result.ofSuccess(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/save.json")
|
|
||||||
@AuthAction(PrivilegeType.WRITE_RULE)
|
|
||||||
public Result<DegradeRuleEntity> updateIfNotNull(Long id, String app, String limitApp, String resource,
|
|
||||||
Double count, Integer timeWindow, Integer grade) {
|
|
||||||
if (id == null) {
|
|
||||||
return Result.ofFail(-1, "id can't be null");
|
|
||||||
}
|
|
||||||
if (grade != null) {
|
|
||||||
if (grade < RuleConstant.DEGRADE_GRADE_RT || grade > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
|
|
||||||
return Result.ofFail(-1, "Invalid grade: " + grade);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DegradeRuleEntity entity = repository.findById(id);
|
|
||||||
if (entity == null) {
|
|
||||||
return Result.ofFail(-1, "id " + id + " dose not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtil.isNotBlank(app)) {
|
|
||||||
entity.setApp(app.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtil.isNotBlank(limitApp)) {
|
|
||||||
entity.setLimitApp(limitApp.trim());
|
|
||||||
}
|
|
||||||
if (StringUtil.isNotBlank(resource)) {
|
|
||||||
entity.setResource(resource.trim());
|
|
||||||
}
|
|
||||||
if (count != null) {
|
|
||||||
entity.setCount(count);
|
|
||||||
}
|
|
||||||
if (timeWindow != null) {
|
|
||||||
entity.setTimeWindow(timeWindow);
|
|
||||||
}
|
|
||||||
if (grade != null) {
|
|
||||||
entity.setGrade(grade);
|
|
||||||
}
|
|
||||||
Date date = new Date();
|
|
||||||
entity.setGmtModified(date);
|
|
||||||
try {
|
|
||||||
entity = repository.save(entity);
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
logger.error("save error:", throwable);
|
|
||||||
return Result.ofThrowable(-1, throwable);
|
|
||||||
}
|
}
|
||||||
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
|
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
|
||||||
logger.info("publish degrade rules fail after rule update");
|
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
|
||||||
}
|
}
|
||||||
return Result.ofSuccess(entity);
|
return Result.ofSuccess(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResponseBody
|
@PutMapping("/rule/{id}")
|
||||||
@RequestMapping("/delete.json")
|
@AuthAction(PrivilegeType.WRITE_RULE)
|
||||||
|
public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id,
|
||||||
|
@RequestBody DegradeRuleEntity entity) {
|
||||||
|
if (id == null || id <= 0) {
|
||||||
|
return Result.ofFail(-1, "id can't be null or negative");
|
||||||
|
}
|
||||||
|
DegradeRuleEntity oldEntity = repository.findById(id);
|
||||||
|
if (oldEntity == null) {
|
||||||
|
return Result.ofFail(-1, "Degrade rule does not exist, id=" + id);
|
||||||
|
}
|
||||||
|
entity.setApp(oldEntity.getApp());
|
||||||
|
entity.setIp(oldEntity.getIp());
|
||||||
|
entity.setPort(oldEntity.getPort());
|
||||||
|
entity.setId(oldEntity.getId());
|
||||||
|
Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
|
||||||
|
if (checkResult != null) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setGmtCreate(oldEntity.getGmtCreate());
|
||||||
|
entity.setGmtModified(new Date());
|
||||||
|
try {
|
||||||
|
entity = repository.save(entity);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
|
||||||
|
return Result.ofThrowable(-1, t);
|
||||||
|
}
|
||||||
|
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
|
||||||
|
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
|
||||||
|
}
|
||||||
|
return Result.ofSuccess(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/rule/{id}")
|
||||||
@AuthAction(PrivilegeType.DELETE_RULE)
|
@AuthAction(PrivilegeType.DELETE_RULE)
|
||||||
public Result<Long> delete(Long id) {
|
public Result<Long> delete(@PathVariable("id") Long id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return Result.ofFail(-1, "id can't be null");
|
return Result.ofFail(-1, "id can't be null");
|
||||||
}
|
}
|
||||||
|
|
@ -198,11 +152,11 @@ public class DegradeController {
|
||||||
try {
|
try {
|
||||||
repository.delete(id);
|
repository.delete(id);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
logger.error("delete error:", throwable);
|
logger.error("Failed to delete degrade rule, id={}", id, throwable);
|
||||||
return Result.ofThrowable(-1, throwable);
|
return Result.ofThrowable(-1, throwable);
|
||||||
}
|
}
|
||||||
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
|
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
|
||||||
logger.info("publish degrade rules fail after rule delete");
|
logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
|
||||||
}
|
}
|
||||||
return Result.ofSuccess(id);
|
return Result.ofSuccess(id);
|
||||||
}
|
}
|
||||||
|
|
@ -211,4 +165,57 @@ public class DegradeController {
|
||||||
List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
|
List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
|
||||||
return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
|
return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) {
|
||||||
|
if (StringUtil.isBlank(entity.getApp())) {
|
||||||
|
return Result.ofFail(-1, "app can't be blank");
|
||||||
|
}
|
||||||
|
if (StringUtil.isBlank(entity.getIp())) {
|
||||||
|
return Result.ofFail(-1, "ip can't be null or empty");
|
||||||
|
}
|
||||||
|
if (entity.getPort() == null || entity.getPort() <= 0) {
|
||||||
|
return Result.ofFail(-1, "invalid port: " + entity.getPort());
|
||||||
|
}
|
||||||
|
if (StringUtil.isBlank(entity.getLimitApp())) {
|
||||||
|
return Result.ofFail(-1, "limitApp can't be null or empty");
|
||||||
|
}
|
||||||
|
if (StringUtil.isBlank(entity.getResource())) {
|
||||||
|
return Result.ofFail(-1, "resource can't be null or empty");
|
||||||
|
}
|
||||||
|
Double threshold = entity.getCount();
|
||||||
|
if (threshold == null || threshold < 0) {
|
||||||
|
return Result.ofFail(-1, "invalid threshold: " + threshold);
|
||||||
|
}
|
||||||
|
Integer recoveryTimeoutSec = entity.getTimeWindow();
|
||||||
|
if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) {
|
||||||
|
return Result.ofFail(-1, "recoveryTimeout should be positive");
|
||||||
|
}
|
||||||
|
Integer strategy = entity.getGrade();
|
||||||
|
if (strategy == null) {
|
||||||
|
return Result.ofFail(-1, "circuit breaker strategy cannot be null");
|
||||||
|
}
|
||||||
|
if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()
|
||||||
|
|| strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
|
||||||
|
return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy);
|
||||||
|
}
|
||||||
|
if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount() <= 0) {
|
||||||
|
return Result.ofFail(-1, "Invalid minRequestAmount");
|
||||||
|
}
|
||||||
|
if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) {
|
||||||
|
return Result.ofFail(-1, "Invalid statInterval");
|
||||||
|
}
|
||||||
|
if (strategy == RuleConstant.DEGRADE_GRADE_RT) {
|
||||||
|
Double slowRatio = entity.getSlowRatioThreshold();
|
||||||
|
if (slowRatio == null) {
|
||||||
|
return Result.ofFail(-1, "SlowRatioThreshold is required for slow request ratio strategy");
|
||||||
|
} else if (slowRatio < 0 || slowRatio > 1) {
|
||||||
|
return Result.ofFail(-1, "SlowRatioThreshold should be in range: [0.0, 1.0]");
|
||||||
|
}
|
||||||
|
} else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
|
||||||
|
if (threshold > 1) {
|
||||||
|
return Result.ofFail(-1, "Ratio threshold should be in range: [0.0, 1.0]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,22 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
||||||
* @author leyou
|
* @author leyou
|
||||||
*/
|
*/
|
||||||
public class DegradeRuleEntity implements RuleEntity {
|
public class DegradeRuleEntity implements RuleEntity {
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
private String app;
|
private String app;
|
||||||
|
|
||||||
private String ip;
|
private String ip;
|
||||||
private Integer port;
|
private Integer port;
|
||||||
|
|
||||||
private String resource;
|
private String resource;
|
||||||
private String limitApp;
|
private String limitApp;
|
||||||
private Double count;
|
private Double count;
|
||||||
private Integer timeWindow;
|
private Integer timeWindow;
|
||||||
/**
|
|
||||||
* 0 rt 限流; 1为异常;
|
|
||||||
*/
|
|
||||||
private Integer grade;
|
private Integer grade;
|
||||||
|
private Integer minRequestAmount;
|
||||||
|
private Double slowRatioThreshold;
|
||||||
|
private Integer statIntervalMs;
|
||||||
|
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
private Date gmtModified;
|
private Date gmtModified;
|
||||||
|
|
||||||
|
|
@ -48,6 +52,9 @@ public class DegradeRuleEntity implements RuleEntity {
|
||||||
entity.setCount(rule.getCount());
|
entity.setCount(rule.getCount());
|
||||||
entity.setTimeWindow(rule.getTimeWindow());
|
entity.setTimeWindow(rule.getTimeWindow());
|
||||||
entity.setGrade(rule.getGrade());
|
entity.setGrade(rule.getGrade());
|
||||||
|
entity.setMinRequestAmount(rule.getMinRequestAmount());
|
||||||
|
entity.setSlowRatioThreshold(rule.getSlowRatioThreshold());
|
||||||
|
entity.setStatIntervalMs(rule.getStatIntervalMs());
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,6 +135,33 @@ public class DegradeRuleEntity implements RuleEntity {
|
||||||
this.grade = grade;
|
this.grade = grade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getMinRequestAmount() {
|
||||||
|
return minRequestAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DegradeRuleEntity setMinRequestAmount(Integer minRequestAmount) {
|
||||||
|
this.minRequestAmount = minRequestAmount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getSlowRatioThreshold() {
|
||||||
|
return slowRatioThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DegradeRuleEntity setSlowRatioThreshold(Double slowRatioThreshold) {
|
||||||
|
this.slowRatioThreshold = slowRatioThreshold;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatIntervalMs() {
|
||||||
|
return statIntervalMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DegradeRuleEntity setStatIntervalMs(Integer statIntervalMs) {
|
||||||
|
this.statIntervalMs = statIntervalMs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Date getGmtCreate() {
|
public Date getGmtCreate() {
|
||||||
return gmtCreate;
|
return gmtCreate;
|
||||||
|
|
@ -153,6 +187,16 @@ public class DegradeRuleEntity implements RuleEntity {
|
||||||
rule.setCount(count);
|
rule.setCount(count);
|
||||||
rule.setTimeWindow(timeWindow);
|
rule.setTimeWindow(timeWindow);
|
||||||
rule.setGrade(grade);
|
rule.setGrade(grade);
|
||||||
|
if (minRequestAmount != null) {
|
||||||
|
rule.setMinRequestAmount(minRequestAmount);
|
||||||
|
}
|
||||||
|
if (slowRatioThreshold != null) {
|
||||||
|
rule.setSlowRatioThreshold(slowRatioThreshold);
|
||||||
|
}
|
||||||
|
if (statIntervalMs != null) {
|
||||||
|
rule.setStatIntervalMs(statIntervalMs);
|
||||||
|
}
|
||||||
|
|
||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,9 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
|
||||||
app: $scope.app,
|
app: $scope.app,
|
||||||
ip: mac[0],
|
ip: mac[0],
|
||||||
port: mac[1],
|
port: mac[1],
|
||||||
limitApp: 'default'
|
limitApp: 'default',
|
||||||
|
minRequestAmount: 5,
|
||||||
|
statIntervalMs: 1000,
|
||||||
};
|
};
|
||||||
$scope.degradeRuleDialog = {
|
$scope.degradeRuleDialog = {
|
||||||
title: '新增降级规则',
|
title: '新增降级规则',
|
||||||
|
|
@ -95,7 +97,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
|
||||||
function parseDegradeMode(grade) {
|
function parseDegradeMode(grade) {
|
||||||
switch (grade) {
|
switch (grade) {
|
||||||
case 0:
|
case 0:
|
||||||
return 'RT';
|
return '慢调用比例';
|
||||||
case 1:
|
case 1:
|
||||||
return '异常比例';
|
return '异常比例';
|
||||||
case 2:
|
case 2:
|
||||||
|
|
@ -137,7 +139,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
|
||||||
getMachineRules();
|
getMachineRules();
|
||||||
confirmDialog.close();
|
confirmDialog.close();
|
||||||
} else {
|
} else {
|
||||||
alert('失败!');
|
alert('失败:' + data.msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -148,7 +150,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
|
||||||
getMachineRules();
|
getMachineRules();
|
||||||
degradeRuleDialog.close();
|
degradeRuleDialog.close();
|
||||||
} else {
|
} else {
|
||||||
alert('失败!');
|
alert('失败:' + data.msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -163,7 +165,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
|
||||||
confirmDialog.close();
|
confirmDialog.close();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('失败!');
|
alert('失败:' + data.msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,8 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
||||||
strategy: 0,
|
strategy: 0,
|
||||||
resource: resource,
|
resource: resource,
|
||||||
limitApp: 'default',
|
limitApp: 'default',
|
||||||
|
minRequestAmount: 5,
|
||||||
|
statIntervalMs: 1000,
|
||||||
app: $scope.app,
|
app: $scope.app,
|
||||||
ip: mac[0],
|
ip: mac[0],
|
||||||
port: mac[1]
|
port: mac[1]
|
||||||
|
|
|
||||||
|
|
@ -15,21 +15,10 @@ app.service('DegradeService', ['$http', function ($http) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.newRule = function (rule) {
|
this.newRule = function (rule) {
|
||||||
var param = {
|
|
||||||
id: rule.id,
|
|
||||||
resource: rule.resource,
|
|
||||||
limitApp: rule.limitApp,
|
|
||||||
count: rule.count,
|
|
||||||
timeWindow: rule.timeWindow,
|
|
||||||
grade: rule.grade,
|
|
||||||
app: rule.app,
|
|
||||||
ip: rule.ip,
|
|
||||||
port: rule.port
|
|
||||||
};
|
|
||||||
return $http({
|
return $http({
|
||||||
url: '/degrade/new.json',
|
url: '/degrade/rule',
|
||||||
params: param,
|
data: rule,
|
||||||
method: 'GET'
|
method: 'POST'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,24 +30,22 @@ app.service('DegradeService', ['$http', function ($http) {
|
||||||
grade: rule.grade,
|
grade: rule.grade,
|
||||||
count: rule.count,
|
count: rule.count,
|
||||||
timeWindow: rule.timeWindow,
|
timeWindow: rule.timeWindow,
|
||||||
|
statIntervalMs: rule.statIntervalMs,
|
||||||
|
minRequestAmount: rule.minRequestAmount,
|
||||||
|
slowRatioThreshold: rule.slowRatioThreshold,
|
||||||
};
|
};
|
||||||
return $http({
|
return $http({
|
||||||
url: '/degrade/save.json',
|
url: '/degrade/rule/' + rule.id,
|
||||||
params: param,
|
data: param,
|
||||||
method: 'GET'
|
method: 'PUT'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.deleteRule = function (rule) {
|
this.deleteRule = function (rule) {
|
||||||
var param = {
|
return $http({
|
||||||
id: rule.id,
|
url: '/degrade/rule/' + rule.id,
|
||||||
app: rule.app
|
method: 'DELETE'
|
||||||
};
|
});
|
||||||
return $http({
|
|
||||||
url: '/degrade/delete.json',
|
|
||||||
params: param,
|
|
||||||
method: 'GET'
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.checkRuleValid = function (rule) {
|
this.checkRuleValid = function (rule) {
|
||||||
|
|
@ -74,8 +61,20 @@ app.service('DegradeService', ['$http', function ($http) {
|
||||||
alert('降级阈值不能为空或小于 0');
|
alert('降级阈值不能为空或小于 0');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (rule.timeWindow === undefined || rule.timeWindow === '' || rule.timeWindow <= 0) {
|
if (rule.timeWindow == undefined || rule.timeWindow === '' || rule.timeWindow <= 0) {
|
||||||
alert('降级时间窗口必须大于 0');
|
alert('熔断时长必须大于 0s');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.minRequestAmount == undefined || rule.minRequestAmount <= 0) {
|
||||||
|
alert('最小请求数目需大于 0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.statIntervalMs == undefined || rule.statIntervalMs <= 0) {
|
||||||
|
alert('统计窗口时长需大于 0s');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.statIntervalMs !== undefined && rule.statIntervalMs > 60 * 1000 * 2) {
|
||||||
|
alert('统计窗口时长不能超过 120 分钟');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 异常比率类型.
|
// 异常比率类型.
|
||||||
|
|
@ -83,6 +82,16 @@ app.service('DegradeService', ['$http', function ($http) {
|
||||||
alert('异常比率超出范围:[0.0 - 1.0]');
|
alert('异常比率超出范围:[0.0 - 1.0]');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (rule.grade == 0) {
|
||||||
|
if (rule.slowRatioThreshold == undefined) {
|
||||||
|
alert('慢调用比率不能为空');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.slowRatioThreshold < 0 || rule.slowRatioThreshold > 1) {
|
||||||
|
alert('慢调用比率超出范围:[0.0 - 1.0]');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
@ -33,21 +33,15 @@
|
||||||
<td style="width: 40%">
|
<td style="width: 40%">
|
||||||
资源名
|
资源名
|
||||||
</td>
|
</td>
|
||||||
<!--<td style="width: 10%;">-->
|
|
||||||
<!--降级应用-->
|
|
||||||
<!--</td>-->
|
|
||||||
<td style="width: 10%;">
|
<td style="width: 10%;">
|
||||||
降级模式
|
降级策略
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 10%;">
|
<td style="width: 10%;">
|
||||||
阈值
|
阈值
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 10%;">
|
<td style="width: 10%;">
|
||||||
时间窗口(s)
|
熔断时长(s)
|
||||||
</td>
|
</td>
|
||||||
<!--<td style="width: 8%;">-->
|
|
||||||
<!--状态-->
|
|
||||||
<!--</td>-->
|
|
||||||
<td style="width: 12%;">
|
<td style="width: 12%;">
|
||||||
操作
|
操作
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -59,9 +53,9 @@
|
||||||
<td style="word-wrap:break-word;word-break:break-all;">{{rule.resource}}</td>
|
<td style="word-wrap:break-word;word-break:break-all;">{{rule.resource}}</td>
|
||||||
<!--<td style="word-wrap:break-word;word-break:break-all;">{{rule.limitApp }}</td>-->
|
<!--<td style="word-wrap:break-word;word-break:break-all;">{{rule.limitApp }}</td>-->
|
||||||
<td>
|
<td>
|
||||||
<span ng-if="rule.grade == 0">RT</span>
|
<span ng-if="rule.grade == 0">慢调用比例</span>
|
||||||
<span ng-if="rule.grade == 1" title="秒级异常比例">异常比例</span>
|
<span ng-if="rule.grade == 1" title="异常比例">异常比例</span>
|
||||||
<span ng-if="rule.grade == 2" title="分钟级异常数">异常数</span>
|
<span ng-if="rule.grade == 2" title="异常数">异常数</span>
|
||||||
</td>
|
</td>
|
||||||
<td style="word-wrap:break-word;word-break:break-all;">
|
<td style="word-wrap:break-word;word-break:break-all;">
|
||||||
{{rule.count}}
|
{{rule.count}}
|
||||||
|
|
|
||||||
|
|
@ -22,30 +22,53 @@
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">降级策略</label>
|
<label class="col-sm-2 control-label">熔断策略</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="form-control highlight-border" align="center">
|
<div class="form-control highlight-border" align="center">
|
||||||
<input type="radio" name="grade" value="0" checked ng-model='currentRule.grade' title="秒级平均响应时间" /> RT
|
<input type="radio" name="grade" value="0" checked ng-model='currentRule.grade' title="慢调用比例(1.8.0+ 版本生效)" /> 慢调用比例
|
||||||
<input type="radio" name="grade" value="1" ng-model='currentRule.grade' title="秒级异常比例" /> 异常比例
|
<input type="radio" name="grade" value="1" ng-model='currentRule.grade' title="异常比例" /> 异常比例
|
||||||
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' title="分钟级异常数,仅 1.3.0 及以上版本生效" /> 异常数
|
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' title="异常数" /> 异常数
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label ng-if="currentRule.grade == 0" class="col-sm-2 control-label">RT</label>
|
<label ng-if="currentRule.grade == 0" class="col-sm-2 control-label" title="最大 RT,超过该值则计为慢调用">最大 RT</label>
|
||||||
<label ng-if="currentRule.grade == 1" class="col-sm-2 control-label">异常比例</label>
|
<label ng-if="currentRule.grade == 1" class="col-sm-2 control-label">比例阈值</label>
|
||||||
<label ng-if="currentRule.grade == 2" class="col-sm-2 control-label">异常数</label>
|
<label ng-if="currentRule.grade == 2" class="col-sm-2 control-label">异常数</label>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-4">
|
||||||
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 0" placeholder="毫秒"/>
|
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 0" placeholder="RT (毫秒)"/>
|
||||||
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 1" placeholder="0.0~1.0"/>
|
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 1" placeholder="取值范围 [0.0,1.0]"/>
|
||||||
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 2" placeholder="异常数"/>
|
<input type='number' class="form-control highlight-border" ng-model='currentRule.count' ng-if="currentRule.grade == 2" placeholder="异常数"/>
|
||||||
</div>
|
</div>
|
||||||
<label class="col-sm-2 control-label">时间窗口</label>
|
<div ng-if="currentRule.grade == 0">
|
||||||
<div class="col-sm-4">
|
<label class="col-sm-2 control-label">比例阈值</label>
|
||||||
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.timeWindow' placeholder="降级时间间隔, 单位秒" />
|
<div class="col-sm-3">
|
||||||
|
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.slowRatioThreshold'
|
||||||
|
placeholder="取值 [0.0, 1.0]" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">熔断时长</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.timeWindow'
|
||||||
|
placeholder="熔断时长(s)" />
|
||||||
|
<span class="input-group-addon">s</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="col-sm-2 control-label" style="text-align: center; padding-right: 5px;"
|
||||||
|
title="触发熔断的最小请求数目,若当前统计窗口内的请求数小于此值,即使达到熔断条件规则也不会触发">最小请求数</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type='number' min="1" class="form-control highlight-border" ng-model='currentRule.minRequestAmount'
|
||||||
|
placeholder="最小请求数目" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
|
|
||||||
2
sentinel-dashboard/src/main/webapp/resources/dist/js/app.js
vendored
Normal file → Executable file
2
sentinel-dashboard/src/main/webapp/resources/dist/js/app.js
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -48,7 +48,7 @@ const JS_APP = [
|
||||||
'app/scripts/services/appservice.js',
|
'app/scripts/services/appservice.js',
|
||||||
'app/scripts/services/flow_service_v1.js',
|
'app/scripts/services/flow_service_v1.js',
|
||||||
'app/scripts/services/flow_service_v2.js',
|
'app/scripts/services/flow_service_v2.js',
|
||||||
'app/scripts/services/degradeservice.js',
|
'app/scripts/services/degrade_service.js',
|
||||||
'app/scripts/services/systemservice.js',
|
'app/scripts/services/systemservice.js',
|
||||||
'app/scripts/services/machineservice.js',
|
'app/scripts/services/machineservice.js',
|
||||||
'app/scripts/services/identityservice.js',
|
'app/scripts/services/identityservice.js',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue