Browse Source

dashboard: Refactor degrade service/controller and adapt to new features

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao 4 years ago
parent
commit
5334f51d21
10 changed files with 241 additions and 160 deletions
  1. +106
    -99
      sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
  2. +47
    -3
      sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/DegradeRuleEntity.java
  3. +7
    -5
      sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js
  4. +2
    -0
      sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js
  5. +37
    -28
      sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degrade_service.js
  6. +5
    -11
      sentinel-dashboard/src/main/webapp/resources/app/views/degrade.html
  7. +34
    -11
      sentinel-dashboard/src/main/webapp/resources/app/views/dialog/degrade-rule-dialog.html
  8. +1
    -1
      sentinel-dashboard/src/main/webapp/resources/dist/js/app.js
  9. +1
    -1
      sentinel-dashboard/src/main/webapp/resources/dist/js/app.vendor.js
  10. +1
    -1
      sentinel-dashboard/src/main/webapp/resources/gulpfile.js

+ 106
- 99
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java View File

@@ -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.discovery.MachineInfo;
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.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.util.StringUtil;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore;

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.DeleteMapping;
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.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
@RequestMapping(value = "/degrade", produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
@RequestMapping("/degrade")
public class DegradeController {

private final Logger logger = LoggerFactory.getLogger(DegradeController.class);

@Autowired
private InMemDegradeRuleStore repository;
private RuleRepository<DegradeRuleEntity, Long> repository;
@Autowired
private SentinelApiClient sentinelApiClient;

@ResponseBody
@RequestMapping("/rules.json")
@GetMapping("/rules.json")
@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)) {
return Result.ofFail(-1, "app can't be null or empty");
}
@@ -75,117 +81,65 @@ public class DegradeController {
}
}

@ResponseBody
@RequestMapping("/new.json")
@PostMapping("/rule")
@AuthAction(PrivilegeType.WRITE_RULE)
public Result<DegradeRuleEntity> add(String app, String ip, Integer port, String limitApp, String resource,
Double count, Integer timeWindow, Integer grade) {
if (StringUtil.isBlank(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
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");
public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) {
Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
}
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();
entity.setGmtCreate(date);
entity.setGmtModified(date);
try {
entity = repository.save(entity);
} catch (Throwable throwable) {
logger.error("add error:", throwable);
return Result.ofThrowable(-1, throwable);
} catch (Throwable t) {
logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
return Result.ofThrowable(-1, t);
}
if (!publishRules(app, ip, port)) {
logger.info("publish degrade rules fail after rule add");
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
return Result.ofSuccess(entity);
}

@ResponseBody
@RequestMapping("/save.json")
@PutMapping("/rule/{id}")
@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");
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");
}
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");
DegradeRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofFail(-1, "Degrade rule does not exist, id=" + id);
}

if (StringUtil.isNotBlank(app)) {
entity.setApp(app.trim());
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;
}

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);
entity.setGmtCreate(oldEntity.getGmtCreate());
entity.setGmtModified(new Date());
try {
entity = repository.save(entity);
} catch (Throwable throwable) {
logger.error("save error:", throwable);
return Result.ofThrowable(-1, throwable);
} 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.info("publish degrade rules fail after rule update");
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
return Result.ofSuccess(entity);
}

@ResponseBody
@RequestMapping("/delete.json")
@DeleteMapping("/rule/{id}")
@AuthAction(PrivilegeType.DELETE_RULE)
public Result<Long> delete(Long id) {
public Result<Long> delete(@PathVariable("id") Long id) {
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -198,11 +152,11 @@ public class DegradeController {
try {
repository.delete(id);
} catch (Throwable throwable) {
logger.error("delete error:", throwable);
logger.error("Failed to delete degrade rule, id={}", id, throwable);
return Result.ofThrowable(-1, throwable);
}
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);
}
@@ -211,4 +165,57 @@ public class DegradeController {
List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
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;
}
}

+ 47
- 3
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/DegradeRuleEntity.java View File

@@ -23,18 +23,22 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
* @author leyou
*/
public class DegradeRuleEntity implements RuleEntity {

private Long id;
private String app;

private String ip;
private Integer port;

private String resource;
private String limitApp;
private Double count;
private Integer timeWindow;
/**
* 0 rt 限流; 1为异常;
*/
private Integer grade;
private Integer minRequestAmount;
private Double slowRatioThreshold;
private Integer statIntervalMs;

private Date gmtCreate;
private Date gmtModified;

@@ -48,6 +52,9 @@ public class DegradeRuleEntity implements RuleEntity {
entity.setCount(rule.getCount());
entity.setTimeWindow(rule.getTimeWindow());
entity.setGrade(rule.getGrade());
entity.setMinRequestAmount(rule.getMinRequestAmount());
entity.setSlowRatioThreshold(rule.getSlowRatioThreshold());
entity.setStatIntervalMs(rule.getStatIntervalMs());
return entity;
}

@@ -128,6 +135,33 @@ public class DegradeRuleEntity implements RuleEntity {
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
public Date getGmtCreate() {
return gmtCreate;
@@ -153,6 +187,16 @@ public class DegradeRuleEntity implements RuleEntity {
rule.setCount(count);
rule.setTimeWindow(timeWindow);
rule.setGrade(grade);
if (minRequestAmount != null) {
rule.setMinRequestAmount(minRequestAmount);
}
if (slowRatioThreshold != null) {
rule.setSlowRatioThreshold(slowRatioThreshold);
}
if (statIntervalMs != null) {
rule.setStatIntervalMs(statIntervalMs);
}

return rule;
}
}

+ 7
- 5
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js View File

@@ -66,7 +66,9 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
app: $scope.app,
ip: mac[0],
port: mac[1],
limitApp: 'default'
limitApp: 'default',
minRequestAmount: 5,
statIntervalMs: 1000,
};
$scope.degradeRuleDialog = {
title: '新增降级规则',
@@ -95,7 +97,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
function parseDegradeMode(grade) {
switch (grade) {
case 0:
return 'RT';
return '慢调用比例';
case 1:
return '异常比例';
case 2:
@@ -137,7 +139,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
getMachineRules();
confirmDialog.close();
} else {
alert('失败!');
alert('失败:' + data.msg);
}
});
};
@@ -148,7 +150,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
getMachineRules();
degradeRuleDialog.close();
} else {
alert('失败!');
alert('失败:' + data.msg);
}
});
};
@@ -163,7 +165,7 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia
confirmDialog.close();
}
} else {
alert('失败!');
alert('失败:' + data.msg);
}
});
}


+ 2
- 0
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js View File

@@ -132,6 +132,8 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
strategy: 0,
resource: resource,
limitApp: 'default',
minRequestAmount: 5,
statIntervalMs: 1000,
app: $scope.app,
ip: mac[0],
port: mac[1]


sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degradeservice.js → sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degrade_service.js View File

@@ -15,21 +15,10 @@ app.service('DegradeService', ['$http', function ($http) {
};

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({
url: '/degrade/new.json',
params: param,
method: 'GET'
url: '/degrade/rule',
data: rule,
method: 'POST'
});
};

@@ -41,24 +30,22 @@ app.service('DegradeService', ['$http', function ($http) {
grade: rule.grade,
count: rule.count,
timeWindow: rule.timeWindow,
statIntervalMs: rule.statIntervalMs,
minRequestAmount: rule.minRequestAmount,
slowRatioThreshold: rule.slowRatioThreshold,
};
return $http({
url: '/degrade/save.json',
params: param,
method: 'GET'
url: '/degrade/rule/' + rule.id,
data: param,
method: 'PUT'
});
};

this.deleteRule = function (rule) {
var param = {
id: rule.id,
app: rule.app
};
return $http({
url: '/degrade/delete.json',
params: param,
method: 'GET'
});
return $http({
url: '/degrade/rule/' + rule.id,
method: 'DELETE'
});
};

this.checkRuleValid = function (rule) {
@@ -74,8 +61,20 @@ app.service('DegradeService', ['$http', function ($http) {
alert('降级阈值不能为空或小于 0');
return false;
}
if (rule.timeWindow === undefined || rule.timeWindow === '' || rule.timeWindow <= 0) {
alert('降级时间窗口必须大于 0');
if (rule.timeWindow == undefined || rule.timeWindow === '' || rule.timeWindow <= 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;
}
// 异常比率类型.
@@ -83,6 +82,16 @@ app.service('DegradeService', ['$http', function ($http) {
alert('异常比率超出范围:[0.0 - 1.0]');
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;
};
}]);

+ 5
- 11
sentinel-dashboard/src/main/webapp/resources/app/views/degrade.html View File

@@ -33,21 +33,15 @@
<td style="width: 40%">
资源名
</td>
<!--<td style="width: 10%;">-->
<!--降级应用-->
<!--</td>-->
<td style="width: 10%;">
降级模式
降级策略
</td>
<td style="width: 10%;">
阈值
</td>
<td style="width: 10%;">
时间窗口(s)
熔断时长(s)
</td>
<!--<td style="width: 8%;">-->
<!--状态-->
<!--</td>-->
<td style="width: 12%;">
操作
</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.limitApp }}</td>-->
<td>
<span ng-if="rule.grade == 0">RT</span>
<span ng-if="rule.grade == 1" title="秒级异常比例">异常比例</span>
<span ng-if="rule.grade == 2" title="分钟级异常数">异常数</span>
<span ng-if="rule.grade == 0">慢调用比例</span>
<span ng-if="rule.grade == 1" title="异常比例">异常比例</span>
<span ng-if="rule.grade == 2" title="异常数">异常数</span>
</td>
<td style="word-wrap:break-word;word-break:break-all;">
{{rule.count}}


+ 34
- 11
sentinel-dashboard/src/main/webapp/resources/app/views/dialog/degrade-rule-dialog.html View File

@@ -22,30 +22,53 @@
<!--</div>-->

<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="form-control highlight-border" align="center">
<input type="radio" name="grade" value="0" checked ng-model='currentRule.grade' title="秒级平均响应时间" />&nbsp;RT&nbsp;&nbsp;
<input type="radio" name="grade" value="1" ng-model='currentRule.grade' title="秒级异常比例" />&nbsp;异常比例&nbsp;&nbsp;
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' title="分钟级异常数,仅 1.3.0 及以上版本生效" />&nbsp;异常数
<input type="radio" name="grade" value="0" checked ng-model='currentRule.grade' title="慢调用比例(1.8.0+ 版本生效)" />&nbsp;慢调用比例&nbsp;&nbsp;
<input type="radio" name="grade" value="1" ng-model='currentRule.grade' title="异常比例" />&nbsp;异常比例&nbsp;&nbsp;
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' title="异常数" />&nbsp;异常数
</div>
</div>
</div>

<div class="form-group">
<label ng-if="currentRule.grade == 0" class="col-sm-2 control-label">RT</label>
<label ng-if="currentRule.grade == 1" class="col-sm-2 control-label">异常比例</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 == 2" class="col-sm-2 control-label">异常数</label>
<div class="col-sm-3">
<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 == 1" placeholder="0.0~1.0"/>
<div class="col-sm-4">
<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 == 2" placeholder="异常数"/>
</div>
<label class="col-sm-2 control-label">时间窗口</label>
<div ng-if="currentRule.grade == 0">
<label class="col-sm-2 control-label">比例阈值</label>
<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 class="form-group">
<label class="col-sm-2 control-label">熔断时长</label>
<div class="col-sm-4">
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.timeWindow' placeholder="降级时间间隔, 单位秒" />
<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>
</div>
<div class="separator"></div>


+ 1
- 1
sentinel-dashboard/src/main/webapp/resources/dist/js/app.js
File diff suppressed because it is too large
View File


+ 1
- 1
sentinel-dashboard/src/main/webapp/resources/dist/js/app.vendor.js
File diff suppressed because it is too large
View File


+ 1
- 1
sentinel-dashboard/src/main/webapp/resources/gulpfile.js View File

@@ -48,7 +48,7 @@ const JS_APP = [
'app/scripts/services/appservice.js',
'app/scripts/services/flow_service_v1.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/machineservice.js',
'app/scripts/services/identityservice.js',


Loading…
Cancel
Save