Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions sentinel-dashboard/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,31 @@
<curator.version>4.0.1</curator.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider add nacos-discovery?

</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
* Sentinel dashboard application.
*
* @author Carpenter Lee
*/
@SpringBootApplication
@EnableDiscoveryClient
public class DashboardApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,19 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.csp.sentinel.dashboard.discovery.AppInfo;
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.domain.vo.MachineInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
* @author Carpenter Lee
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,26 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;

import java.util.Date;
import java.util.List;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
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.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;

import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
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.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;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
* @author Eric Zhao
Expand All @@ -53,6 +46,16 @@ public class AuthorityRuleController {

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

// === 新增:注入 Nacos Provider/Publisher ===
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type of comment seems unnecessary - we can safely remove it to keep the code concise. (the same applies to other similar comments below)

@Autowired
@Qualifier("authorityRuleNacosProvider")
private DynamicRuleProvider<List<AuthorityRuleEntity>> ruleProvider;

@Autowired
@Qualifier("authorityRuleNacosPublisher")
private DynamicRulePublisher<List<AuthorityRuleEntity>> rulePublisher;
// === 新增结束 ===

@Autowired
private SentinelApiClient sentinelApiClient;
@Autowired
Expand All @@ -78,7 +81,8 @@ public Result<List<AuthorityRuleEntity>> apiQueryAllRulesForMachine(@RequestPara
return Result.ofFail(-1, "given ip does not belong to given app");
}
try {
List<AuthorityRuleEntity> rules = sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port);
// === 修改:从 Nacos 获取规则 ===
List<AuthorityRuleEntity> rules = ruleProvider.getRules(app);
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
Expand Down Expand Up @@ -129,6 +133,11 @@ public Result<AuthorityRuleEntity> apiAddAuthorityRule(@RequestBody AuthorityRul
entity.setGmtModified(date);
try {
entity = repository.save(entity);

// === 新增:发布到 Nacos ===
publishRulesToNacos(entity.getApp());
// === 新增结束 ===

} catch (Throwable throwable) {
logger.error("Failed to add authority rule", throwable);
return Result.ofThrowable(-1, throwable);
Expand Down Expand Up @@ -159,6 +168,11 @@ public Result<AuthorityRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Lo
if (entity == null) {
return Result.ofFail(-1, "Failed to save authority rule");
}

// === 新增:发布到 Nacos ===
publishRulesToNacos(entity.getApp());
// === 新增结束 ===

} catch (Throwable throwable) {
logger.error("Failed to save authority rule", throwable);
return Result.ofThrowable(-1, throwable);
Expand All @@ -181,6 +195,11 @@ public Result<Long> apiDeleteRule(@PathVariable("id") Long id) {
}
try {
repository.delete(id);

// === 新增:发布到 Nacos ===
publishRulesToNacos(oldEntity.getApp());
// === 新增结束 ===

} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
Expand All @@ -194,4 +213,11 @@ private boolean publishRules(String app, String ip, Integer port) {
List<AuthorityRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules);
}

// === 新增:发布规则到 Nacos 的方法 ===
private void publishRulesToNacos(String app) throws Exception {
List<AuthorityRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
Comment on lines +218 to +220
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method throws generic Exception. Consider catching and wrapping with a more specific exception or logging the error instead of propagating.

Suggested change
private void publishRulesToNacos(String app) throws Exception {
List<AuthorityRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
private void publishRulesToNacos(String app) {
try {
List<AuthorityRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
} catch (Exception e) {
logger.error("Failed to publish authority rules to Nacos for app: {}", app, e);
throw new RuntimeException("Failed to publish authority rules to Nacos for app: " + app, e);
}

Copilot uses AI. Check for mistakes.
}
// === 新增结束 ===
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,27 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;

import java.util.Date;
import java.util.List;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
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 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.RestController;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
* Controller regarding APIs of degrade rules. Refactored since 1.8.0.
Expand All @@ -55,6 +49,14 @@ public class DegradeController {

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

@Autowired
@Qualifier("degradeRuleNacosProvider")
private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;

@Autowired
@Qualifier("degradeRuleNacosPublisher")
private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;

@Autowired
private RuleRepository<DegradeRuleEntity, Long> repository;
@Autowired
Expand All @@ -78,7 +80,7 @@ public Result<List<DegradeRuleEntity>> apiQueryMachineRules(String app, String i
return Result.ofFail(-1, "given ip does not belong to given app");
}
try {
List<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
List<DegradeRuleEntity> rules = ruleProvider.getRules(app);
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
Expand All @@ -99,13 +101,11 @@ public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entit
entity.setGmtModified(date);
try {
entity = repository.save(entity);
publishRulesToNacos(entity.getApp());
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publishRulesToNacos call should be wrapped in a try-catch block to handle exceptions properly and avoid breaking the rule save operation.

Copilot uses AI. Check for mistakes.
} 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(entity.getApp(), entity.getIp(), entity.getPort())) {
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
return Result.ofSuccess(entity);
}

Expand Down Expand Up @@ -133,13 +133,11 @@ public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id,
entity.setGmtModified(new Date());
try {
entity = repository.save(entity);
publishRulesToNacos(entity.getApp());
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publishRulesToNacos call should be wrapped in a try-catch block to handle exceptions properly and avoid breaking the rule update operation.

Copilot uses AI. Check for mistakes.
} catch (Throwable t) {
logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
return Result.ofThrowable(-1, t);
}
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
return Result.ofSuccess(entity);
}

Expand All @@ -157,13 +155,11 @@ public Result<Long> delete(@PathVariable("id") Long id) {

try {
repository.delete(id);
publishRulesToNacos(oldEntity.getApp());
} catch (Throwable 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.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
}
return Result.ofSuccess(id);
}

Expand All @@ -172,6 +168,11 @@ private boolean publishRules(String app, String ip, Integer port) {
return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
}

private void publishRulesToNacos(String app) throws Exception {
List<DegradeRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
Comment on lines +171 to +173
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method throws generic Exception. Consider catching and wrapping with a more specific exception or logging the error instead of propagating.

Suggested change
private void publishRulesToNacos(String app) throws Exception {
List<DegradeRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
private void publishRulesToNacos(String app) {
try {
List<DegradeRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
} catch (Exception e) {
logger.error("Failed to publish degrade rules to Nacos for app: {}", app, e);
throw new RuntimeException("Failed to publish degrade rules to Nacos for app: " + app, e);
}

Copilot uses AI. Check for mistakes.
}

private <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) {
if (StringUtil.isBlank(entity.getApp())) {
return Result.ofFail(-1, "app can't be blank");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;

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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

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;

@Controller
@RequestMapping(value = "/demo", produces = MediaType.APPLICATION_JSON_VALUE)
Expand Down
Loading
Loading