⬆️ Upgrading dependencies. #1696 up sentinel 1.8

⬆️ Upgrading dependencies. #1696 up sentinel 1.8
This commit is contained in:
冷冷 committed 2020-09-02 08:42:23 +08:00
1 parent 729df9d1c7
commit 03b499568e
145 files changed
+522 -331

No files matched your search

@@ -55,7 +55,6 @@ public class SysRoleController {
/**
* 通过ID查询角色信息
*
* @param id ID
* @return 角色信息
*/
@@ -66,7 +65,6 @@ public class SysRoleController {
/**
* 添加角色
*
* @param sysRole 角色信息
* @return success、false
*/
@@ -80,7 +78,6 @@ public class SysRoleController {
/**
* 修改角色
*
* @param sysRole 角色信息
* @return success/false
*/
@@ -94,7 +91,6 @@ public class SysRoleController {
/**
* 删除角色
*
* @param id
* @return
*/
@@ -108,7 +104,6 @@ public class SysRoleController {
/**
* 获取角色列表
*
* @return 角色列表
*/
@GetMapping("/list")
@@ -118,7 +113,6 @@ public class SysRoleController {
/**
* 分页查询角色信息
*
* @param page 分页对象
* @return 分页对象
*/
@@ -129,7 +123,6 @@ public class SysRoleController {
/**
* 更新角色菜单
*
* @param roleVo 角色对象
* @return success、false
*/
@@ -142,7 +135,6 @@ public class SysRoleController {
/**
* 通过角色ID 查询角色列表
*
* @param roleIdList 角色ID
* @return
*/
@@ -37,7 +37,6 @@ public interface SysRoleService extends IService<SysRole> {
/**
* 通过用户ID,查询角色信息
*
* @param userId
* @return
*/
@@ -45,16 +44,14 @@ public interface SysRoleService extends IService<SysRole> {
/**
* 根据角色ID 查询角色列表
*
* @param roleIdList 角色ID列表
* @param key 缓存key
* @param key 缓存key
* @return
*/
List<SysRole> findRolesByRoleIds(List<Integer> roleIdList, String key);
/**
* 通过角色ID,删除角色
*
* @param id
* @return
*/
@@ -62,9 +59,9 @@ public interface SysRoleService extends IService<SysRole> {
/**
* 根据角色菜单列表
*
* @param roleVo 角色&菜单列表
* @return
*/
Boolean updateRoleMenus(RoleVO roleVo);
}
@@ -51,7 +51,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
/**
* 通过用户ID,查询角色信息
*
* @param userId
* @return
*/
@@ -62,9 +61,8 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
/**
* 根据角色ID 查询角色列表,注意缓存删除
*
* @param roleIdList 角色ID列表
* @param key 缓存key
* @param key 缓存key
* @return
*/
@Override
@@ -75,7 +73,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
/**
* 通过角色ID,删除角色,并清空角色菜单缓存
*
* @param id
* @return
*/
@@ -88,7 +85,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
/**
* 根据角色菜单列表
*
* @param roleVo 角色&菜单列表
* @return
*/
@@ -97,4 +93,5 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
SysRole sysRole = baseMapper.selectById(roleVo.getRoleId());
return roleMenuService.saveRoleMenus(sysRole.getRoleCode(), roleVo.getRoleId(), roleVo.getMenuIds());
}
}
@@ -58,8 +58,7 @@ public class PayGoodsOrderController {
/**
* 商品订单
*
* @param goods 商品
* @param goods 商品
* @param response
* @return R
*/
@@ -86,10 +85,9 @@ public class PayGoodsOrderController {
/**
* oauth
*
* @param goods 商品信息
* @param state appid
* @param code 回调code
* @param goods 商品信息
* @param state appid
* @param code 回调code
* @param modelAndView
* @return
* @throws WxErrorException
@@ -109,8 +107,7 @@ public class PayGoodsOrderController {
/**
* 分页查询
*
* @param page 分页对象
* @param page 分页对象
* @param payGoodsOrder 商品订单表
* @return
*/
@@ -122,7 +119,6 @@ public class PayGoodsOrderController {
/**
* 通过id查询商品订单表
*
* @param goodsOrderId id
* @return R
*/
@@ -134,7 +130,6 @@ public class PayGoodsOrderController {
/**
* 新增商品订单表
*
* @param payGoodsOrder 商品订单表
* @return R
*/
@@ -148,7 +143,6 @@ public class PayGoodsOrderController {
/**
* 修改商品订单表
*
* @param payGoodsOrder 商品订单表
* @return R
*/
@@ -162,7 +156,6 @@ public class PayGoodsOrderController {
/**
* 通过id删除商品订单表
*
* @param goodsOrderId id
* @return R
*/
+1 -11
View File
@@ -42,16 +42,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
@@ -86,8 +76,8 @@
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/webapp/</directory>
<excludes>
@@ -21,9 +21,9 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author nacos
* <p>
* sentinel console 源码运行,方便开发 生产建议从官网下载最新版配置运行
* Sentinel dashboard application.
*
* @author Carpenter Lee
*/
@SpringBootApplication
public class PigxSentinelApplication {
@@ -34,7 +34,7 @@ public class PigxSentinelApplication {
}
private static void triggerSentinelInit() {
new Thread(InitExecutor::doInit).start();
new Thread(() -> InitExecutor.doInit()).start();
}
}
@@ -69,6 +69,7 @@ import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.DefaultRedirectStrategy;
@@ -95,6 +96,11 @@ public class SentinelApiClient {
private static final Charset DEFAULT_CHARSET = Charset.forName(SentinelConfig.charset());
private static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
private static final String HTTP_HEADER_CONTENT_TYPE_URLENCODED = ContentType.create(URLEncodedUtils.CONTENT_TYPE)
.toString();
private static final String RESOURCE_URL_PATH = "jsonTree";
private static final String CLUSTER_NODE_PATH = "clusterNode";
@@ -115,8 +121,6 @@ public class SentinelApiClient {
private static final String MODIFY_CLUSTER_CLIENT_CONFIG_PATH = "cluster/client/modifyConfig";
private static final String FETCH_CLUSTER_SERVER_ALL_CONFIG_PATH = "cluster/server/fetchConfig";
private static final String FETCH_CLUSTER_SERVER_BASIC_INFO_PATH = "cluster/server/info";
private static final String MODIFY_CLUSTER_SERVER_TRANSPORT_CONFIG_PATH = "cluster/server/modifyTransportConfig";
@@ -145,6 +149,8 @@ public class SentinelApiClient {
private static final SentinelVersion version160 = new SentinelVersion(1, 6, 0);
private static final SentinelVersion version171 = new SentinelVersion(1, 7, 1);
@Autowired
private AppManagement appManagement;
@@ -169,6 +175,27 @@ public class SentinelApiClient {
&& body.contains(CommandConstants.MSG_UNKNOWN_COMMAND_PREFIX);
}
protected boolean isSupportPost(String app, String ip, int port) {
return StringUtil.isNotEmpty(app)
&& Optional.ofNullable(appManagement.getDetailApp(app)).flatMap(e -> e.getMachine(ip, port))
.flatMap(m -> VersionUtils.parseVersion(m.getVersion()).map(v -> v.greaterOrEqual(version160)))
.orElse(false);
}
/**
* Check wheter target instance (identified by tuple of app-ip:port) supports the form
* of "xxxxx; xx=xx" in "Content-Type" header.
* @param app target app name
* @param ip target node's address
* @param port target node's port
*/
protected boolean isSupportEnhancedContentType(String app, String ip, int port) {
return StringUtil.isNotEmpty(app)
&& Optional.ofNullable(appManagement.getDetailApp(app)).flatMap(e -> e.getMachine(ip, port))
.flatMap(m -> VersionUtils.parseVersion(m.getVersion()).map(v -> v.greaterOrEqual(version171)))
.orElse(false);
}
private StringBuilder queryString(Map<String, String> params) {
StringBuilder queryStringBuilder = new StringBuilder();
for (Entry<String, String> entry : params.entrySet()) {
@@ -187,7 +214,16 @@ public class SentinelApiClient {
return queryStringBuilder;
}
private HttpUriRequest postRequest(String url, Map<String, String> params) {
/**
* Build an `HttpUriRequest` in POST way.
* @param url
* @param params
* @param supportEnhancedContentType see
* {@link #isSupportEnhancedContentType(String, String, int)}
* @return
*/
protected static HttpUriRequest postRequest(String url, Map<String, String> params,
boolean supportEnhancedContentType) {
HttpPost httpPost = new HttpPost(url);
if (params != null && params.size() > 0) {
List<NameValuePair> list = new ArrayList<>(params.size());
@@ -195,6 +231,9 @@ public class SentinelApiClient {
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
httpPost.setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8));
if (!supportEnhancedContentType) {
httpPost.setHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_HEADER_CONTENT_TYPE_URLENCODED);
}
}
return httpPost;
}
@@ -212,7 +251,7 @@ public class SentinelApiClient {
private String getBody(HttpResponse response) throws Exception {
Charset charset = null;
try {
String contentTypeStr = response.getFirstHeader("Content-type").getValue();
String contentTypeStr = response.getFirstHeader(HTTP_HEADER_CONTENT_TYPE).getValue();
if (StringUtil.isNotEmpty(contentTypeStr)) {
ContentType contentType = ContentType.parse(contentTypeStr);
charset = contentType.getCharset();
@@ -269,11 +308,7 @@ public class SentinelApiClient {
if (params == null) {
params = Collections.emptyMap();
}
boolean supportPost = StringUtil.isNotEmpty(app)
&& Optional.ofNullable(appManagement.getDetailApp(app)).flatMap(e -> e.getMachine(ip, port))
.flatMap(m -> VersionUtils.parseVersion(m.getVersion()).map(v -> v.greaterOrEqual(version160)))
.orElse(false);
if (!useHttpPost || !supportPost) {
if (!useHttpPost || !isSupportPost(app, ip, port)) {
// Using GET in older versions, append parameters after url
if (!params.isEmpty()) {
if (urlBuilder.indexOf("?") == -1) {
@@ -288,7 +323,8 @@ public class SentinelApiClient {
}
else {
// Using POST
return executeCommand(postRequest(urlBuilder.toString(), params));
return executeCommand(
postRequest(urlBuilder.toString(), params, isSupportEnhancedContentType(app, ip, port)));
}
}
@@ -22,41 +22,47 @@ 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");
}
@@ -77,119 +83,66 @@ 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");
public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) {
Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
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();
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 oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofFail(-1, "Degrade rule does not exist, id=" + id);
}
DegradeRuleEntity entity = repository.findById(id);
if (entity == null) {
return Result.ofFail(-1, "id " + id + " dose not exist");
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(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);
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");
}
@@ -203,11 +156,11 @@ public class DegradeController {
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);
}
@@ -217,4 +170,59 @@ public class DegradeController {
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;
}
}
@@ -15,11 +15,9 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
@@ -27,8 +25,11 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
@Controller
@RequestMapping(value = "/demo", produces = MediaType.APPLICATION_JSON_VALUE)
@@ -111,7 +112,7 @@ public class DemoController {
try {
e1 = SphU.entry(name);
if (slow == true) {
if (slow) {
TimeUnit.MILLISECONDS.sleep(3000);
}
@@ -15,30 +15,40 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Eric Zhao
* @since 0.2.1
@@ -110,7 +120,7 @@ public class ParamFlowRuleController {
}
@PostMapping("/rule")
@AuthAction(PrivilegeType.WRITE_RULE)
@AuthAction(AuthService.PrivilegeType.WRITE_RULE)
public Result<ParamFlowRuleEntity> apiAddParamFlowRule(@RequestBody ParamFlowRuleEntity entity) {
Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
@@ -182,7 +192,7 @@ public class ParamFlowRuleController {
}
@PutMapping("/rule/{id}")
@AuthAction(PrivilegeType.WRITE_RULE)
@AuthAction(AuthService.PrivilegeType.WRITE_RULE)
public Result<ParamFlowRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id,
@RequestBody ParamFlowRuleEntity entity) {
if (id == null || id <= 0) {
@@ -147,19 +147,19 @@ public class GatewayFlowRuleController {
return Result.ofFail(-1, "fieldName can't be null or empty");
}
itemEntity.setFieldName(paramItem.getFieldName());
}
String pattern = paramItem.getPattern();
// 如果匹配串不为空,验证匹配模式
if (StringUtil.isNotEmpty(pattern)) {
itemEntity.setPattern(pattern);
Integer matchStrategy = paramItem.getMatchStrategy();
if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS,
PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
}
itemEntity.setMatchStrategy(matchStrategy);
String pattern = paramItem.getPattern();
// 如果匹配串不为空,验证匹配模式
if (StringUtil.isNotEmpty(pattern)) {
itemEntity.setPattern(pattern);
Integer matchStrategy = paramItem.getMatchStrategy();
if (!Arrays
.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX)
.contains(matchStrategy)) {
return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
}
itemEntity.setMatchStrategy(matchStrategy);
}
}
@@ -298,19 +298,19 @@ public class GatewayFlowRuleController {
return Result.ofFail(-1, "fieldName can't be null or empty");
}
itemEntity.setFieldName(paramItem.getFieldName());
}
String pattern = paramItem.getPattern();
// 如果匹配串不为空,验证匹配模式
if (StringUtil.isNotEmpty(pattern)) {
itemEntity.setPattern(pattern);
Integer matchStrategy = paramItem.getMatchStrategy();
if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS,
PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
}
itemEntity.setMatchStrategy(matchStrategy);
String pattern = paramItem.getPattern();
// 如果匹配串不为空,验证匹配模式
if (StringUtil.isNotEmpty(pattern)) {
itemEntity.setPattern(pattern);
Integer matchStrategy = paramItem.getMatchStrategy();
if (!Arrays
.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX)
.contains(matchStrategy)) {
return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
}
itemEntity.setMatchStrategy(matchStrategy);
}
}
else {
@@ -137,7 +137,7 @@ public class FlowControllerV2 {
}
@PostMapping("/rule")
@AuthAction(value = PrivilegeType.WRITE_RULE)
@AuthAction(value = AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
@@ -162,7 +162,7 @@ public class FlowControllerV2 {
}
@PutMapping("/rule/{id}")
@AuthAction(PrivilegeType.WRITE_RULE)
@AuthAction(AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiUpdateFlowRule(@PathVariable("id") Long id, @RequestBody FlowRuleEntity entity) {
if (id == null || id <= 0) {
@@ -71,7 +71,6 @@ public class MetricEntity {
entity.setExceptionQps(oldEntity.getExceptionQps());
entity.setRt(oldEntity.getRt());
entity.setCount(oldEntity.getCount());
entity.setResource(oldEntity.getResource());
return entity;
}
@@ -40,11 +40,14 @@ public class DegradeRuleEntity implements RuleEntity {
private Integer timeWindow;
/**
* 0 rt 限流; 1为异常;
*/
private Integer grade;
private Integer minRequestAmount;
private Double slowRatioThreshold;
private Integer statIntervalMs;
private Date gmtCreate;
private Date gmtModified;
@@ -59,6 +62,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;
}
@@ -139,6 +145,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;
@@ -164,6 +197,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;
}
@@ -15,6 +15,11 @@
*/
package com.alibaba.csp.sentinel.dashboard.repository.metric;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -22,14 +27,9 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import org.springframework.stereotype.Component;
/**
* Caches metrics data in a period of time in memory.
*
@@ -44,56 +44,73 @@ public class InMemoryMetricsRepository implements MetricsRepository<MetricEntity
/**
* {@code app -> resource -> timestamp -> metric}
*/
private Map<String, Map<String, ConcurrentLinkedHashMap<Long, MetricEntity>>> allMetrics = new ConcurrentHashMap<>();
private Map<String, Map<String, LinkedHashMap<Long, MetricEntity>>> allMetrics = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
@Override
public synchronized void save(MetricEntity entity) {
public void save(MetricEntity entity) {
if (entity == null || StringUtil.isBlank(entity.getApp())) {
return;
}
allMetrics.computeIfAbsent(entity.getApp(), e -> new ConcurrentHashMap<>(16))
.computeIfAbsent(entity.getResource(),
e -> new ConcurrentLinkedHashMap.Builder<Long, MetricEntity>()
.maximumWeightedCapacity(MAX_METRIC_LIVE_TIME_MS).weigher((key, value) -> {
// Metric older than {@link #MAX_METRIC_LIVE_TIME_MS}
// will be removed.
int weight = (int) (System.currentTimeMillis() - key);
// weight must be a number greater than or equal to
// one
return Math.max(weight, 1);
}).build())
.put(entity.getTimestamp().getTime(), entity);
readWriteLock.writeLock().lock();
try {
allMetrics.computeIfAbsent(entity.getApp(), e -> new HashMap<>(16))
.computeIfAbsent(entity.getResource(), e -> new LinkedHashMap<Long, MetricEntity>() {
@Override
protected boolean removeEldestEntry(Entry<Long, MetricEntity> eldest) {
// Metric older than {@link #MAX_METRIC_LIVE_TIME_MS} will be
// removed.
return eldest.getKey() < TimeUtil.currentTimeMillis() - MAX_METRIC_LIVE_TIME_MS;
}
}).put(entity.getTimestamp().getTime(), entity);
}
finally {
readWriteLock.writeLock().unlock();
}
}
@Override
public synchronized void saveAll(Iterable<MetricEntity> metrics) {
public void saveAll(Iterable<MetricEntity> metrics) {
if (metrics == null) {
return;
}
metrics.forEach(this::save);
readWriteLock.writeLock().lock();
try {
metrics.forEach(this::save);
}
finally {
readWriteLock.writeLock().unlock();
}
}
@Override
public synchronized List<MetricEntity> queryByAppAndResourceBetween(String app, String resource, long startTime,
long endTime) {
public List<MetricEntity> queryByAppAndResourceBetween(String app, String resource, long startTime, long endTime) {
List<MetricEntity> results = new ArrayList<>();
if (StringUtil.isBlank(app)) {
return results;
}
Map<String, ConcurrentLinkedHashMap<Long, MetricEntity>> resourceMap = allMetrics.get(app);
Map<String, LinkedHashMap<Long, MetricEntity>> resourceMap = allMetrics.get(app);
if (resourceMap == null) {
return results;
}
ConcurrentLinkedHashMap<Long, MetricEntity> metricsMap = resourceMap.get(resource);
LinkedHashMap<Long, MetricEntity> metricsMap = resourceMap.get(resource);
if (metricsMap == null) {
return results;
}
for (Entry<Long, MetricEntity> entry : metricsMap.entrySet()) {
if (entry.getKey() >= startTime && entry.getKey() <= endTime) {
results.add(entry.getValue());
readWriteLock.readLock().lock();
try {
for (Entry<Long, MetricEntity> entry : metricsMap.entrySet()) {
if (entry.getKey() >= startTime && entry.getKey() <= endTime) {
results.add(entry.getValue());
}
}
return results;
}
finally {
readWriteLock.readLock().unlock();
}
return results;
}
@Override
@@ -103,42 +120,48 @@ public class InMemoryMetricsRepository implements MetricsRepository<MetricEntity
return results;
}
// resource -> timestamp -> metric
Map<String, ConcurrentLinkedHashMap<Long, MetricEntity>> resourceMap = allMetrics.get(app);
Map<String, LinkedHashMap<Long, MetricEntity>> resourceMap = allMetrics.get(app);
if (resourceMap == null) {
return results;
}
final long minTimeMs = System.currentTimeMillis() - 1000 * 60;
Map<String, MetricEntity> resourceCount = new ConcurrentHashMap<>(32);
for (Entry<String, ConcurrentLinkedHashMap<Long, MetricEntity>> resourceMetrics : resourceMap.entrySet()) {
for (Entry<Long, MetricEntity> metrics : resourceMetrics.getValue().entrySet()) {
if (metrics.getKey() < minTimeMs) {
continue;
}
MetricEntity newEntity = metrics.getValue();
if (resourceCount.containsKey(resourceMetrics.getKey())) {
MetricEntity oldEntity = resourceCount.get(resourceMetrics.getKey());
oldEntity.addPassQps(newEntity.getPassQps());
oldEntity.addRtAndSuccessQps(newEntity.getRt(), newEntity.getSuccessQps());
oldEntity.addBlockQps(newEntity.getBlockQps());
oldEntity.addExceptionQps(newEntity.getExceptionQps());
oldEntity.addCount(1);
}
else {
resourceCount.put(resourceMetrics.getKey(), MetricEntity.copyOf(newEntity));
readWriteLock.readLock().lock();
try {
for (Entry<String, LinkedHashMap<Long, MetricEntity>> resourceMetrics : resourceMap.entrySet()) {
for (Entry<Long, MetricEntity> metrics : resourceMetrics.getValue().entrySet()) {
if (metrics.getKey() < minTimeMs) {
continue;
}
MetricEntity newEntity = metrics.getValue();
if (resourceCount.containsKey(resourceMetrics.getKey())) {
MetricEntity oldEntity = resourceCount.get(resourceMetrics.getKey());
oldEntity.addPassQps(newEntity.getPassQps());
oldEntity.addRtAndSuccessQps(newEntity.getRt(), newEntity.getSuccessQps());
oldEntity.addBlockQps(newEntity.getBlockQps());
oldEntity.addExceptionQps(newEntity.getExceptionQps());
oldEntity.addCount(1);
}
else {
resourceCount.put(resourceMetrics.getKey(), MetricEntity.copyOf(newEntity));
}
}
}
// Order by last minute b_qps DESC.
return resourceCount.entrySet().stream().sorted((o1, o2) -> {
MetricEntity e1 = o1.getValue();
MetricEntity e2 = o2.getValue();
int t = e2.getBlockQps().compareTo(e1.getBlockQps());
if (t != 0) {
return t;
}
return e2.getPassQps().compareTo(e1.getPassQps());
}).map(Entry::getKey).collect(Collectors.toList());
}
finally {
readWriteLock.readLock().unlock();
}
// Order by last minute b_qps DESC.
return resourceCount.entrySet().stream().sorted((o1, o2) -> {
MetricEntity e1 = o1.getValue();
MetricEntity e2 = o2.getValue();
int t = e2.getBlockQps().compareTo(e1.getBlockQps());
if (t != 0) {
return t;
}
return e2.getPassQps().compareTo(e1.getPassQps());
}).map(Entry::getKey).collect(Collectors.toList());
}
}
@@ -24,4 +24,4 @@ auth:
sentinel:
dashboard:
version: 1.7.1
version: @project.version@
@@ -0,0 +1,32 @@
# Sentinel Dashboard Frontend
## Env Requirement
- Node.js > 6.x
## Code Guide
- [Code Style Guide for HTML/CSS](https://codeguide.bootcss.com/)
- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript/tree/es5-deprecated/es5)
## Install Packages
```
npm install
```
## Start Development
```
npm start
```
## Build for production
```
npm run build
```
## Credit
- [sb-admin-angular](https://github.com/start-angular/sb-admin-angular)
@@ -0,0 +1,32 @@
# Sentinel Dashboard Frontend
## 环境要求
- Node.js > 6.x
## 编码规范
- HTML/CSS 遵循 [Bootstrap 编码规范](https://codeguide.bootcss.com/)
- JavaScript 遵循 [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript/tree/es5-deprecated/es5) 以及最新的 ES 6 标准
## 安装依赖
```
npm i
```
## 开始本地开发
```
npm start
```
## 构建前端资源
```
npm run build
```
## Credit
- [sb-admin-angular](https://github.com/start-angular/sb-admin-angular)
File mode changed.
@@ -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);
}
});
}
@@ -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]
File mode changed.
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more