⬆️ Upgrading dependencies. #1696 up sentinel 1.8
⬆️ Upgrading dependencies. #1696 up sentinel 1.8
This commit is contained in:
1 parent
729df9d1c7
commit
03b499568e
145 files changed
+522
-331
No files matched your search
-8
@@ -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
|
||||
*/
|
||||
|
||||
+2
-5
@@ -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);
|
||||
|
||||
}
|
||||
+2
-5
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+5
-12
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
+4
-4
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+46
-10
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+107
-99
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+9
-8
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+30
-20
@@ -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) {
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
+22
-22
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+46
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
+80
-57
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
@@ -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)
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+7
-5
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+2
@@ -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]
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user