Commit f64a4cff1b929cff51f6540c2c201fb085dc30cf
1 parent
410f1531
【新版发布3.2.0】 sentinel深度改造支持持久化到nacos
Showing
32 changed files
with
3078 additions
and
33 deletions
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/README.md
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/pom.xml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <parent> |
6 | 6 | <artifactId>jeecg-cloud-module</artifactId> |
7 | 7 | <groupId>org.jeecgframework.boot</groupId> |
8 | - <version>3.1.0</version> | |
8 | + <version>3.2.0</version> | |
9 | 9 | </parent> |
10 | 10 | <artifactId>jeecg-cloud-sentinel</artifactId> |
11 | 11 | <name>jeecg-cloud-sentinel</name> |
... | ... | @@ -34,31 +34,87 @@ |
34 | 34 | <dependency> |
35 | 35 | <groupId>org.jeecgframework.cloud</groupId> |
36 | 36 | <artifactId>sentinel-dashboard</artifactId> |
37 | - <version>1.8.2</version> | |
37 | + <version>1.8.3</version> | |
38 | + <exclusions> | |
39 | + <exclusion> | |
40 | + <artifactId>sentinel-web-servlet</artifactId> | |
41 | + <groupId>com.alibaba.csp</groupId> | |
42 | + </exclusion> | |
43 | + <exclusion> | |
44 | + <artifactId>sentinel-transport-simple-http</artifactId> | |
45 | + <groupId>com.alibaba.csp</groupId> | |
46 | + </exclusion> | |
47 | + <exclusion> | |
48 | + <artifactId>sentinel-parameter-flow-control</artifactId> | |
49 | + <groupId>com.alibaba.csp</groupId> | |
50 | + </exclusion> | |
51 | + <exclusion> | |
52 | + <artifactId>sentinel-core</artifactId> | |
53 | + <groupId>com.alibaba.csp</groupId> | |
54 | + </exclusion> | |
55 | + <exclusion> | |
56 | + <artifactId>sentinel-api-gateway-adapter-common</artifactId> | |
57 | + <groupId>com.alibaba.csp</groupId> | |
58 | + </exclusion> | |
59 | + </exclusions> | |
38 | 60 | </dependency> |
39 | 61 | <dependency> |
40 | 62 | <groupId>com.alibaba.csp</groupId> |
41 | 63 | <artifactId>sentinel-datasource-nacos</artifactId> |
64 | + <version>1.8.3</version> | |
65 | + <exclusions> | |
66 | + <exclusion> | |
67 | + <artifactId>sentinel-core</artifactId> | |
68 | + <groupId>com.alibaba.csp</groupId> | |
69 | + </exclusion> | |
70 | + </exclusions> | |
42 | 71 | </dependency> |
43 | 72 | <dependency> |
44 | 73 | <groupId>com.alibaba.csp</groupId> |
45 | 74 | <artifactId>sentinel-core</artifactId> |
75 | + <version>1.8.3</version> | |
46 | 76 | </dependency> |
47 | 77 | <dependency> |
48 | 78 | <groupId>com.alibaba.csp</groupId> |
49 | 79 | <artifactId>sentinel-web-servlet</artifactId> |
80 | + <version>1.8.3</version> | |
81 | + <exclusions> | |
82 | + <exclusion> | |
83 | + <artifactId>sentinel-core</artifactId> | |
84 | + <groupId>com.alibaba.csp</groupId> | |
85 | + </exclusion> | |
86 | + </exclusions> | |
50 | 87 | </dependency> |
51 | 88 | <dependency> |
52 | 89 | <groupId>com.alibaba.csp</groupId> |
53 | 90 | <artifactId>sentinel-transport-simple-http</artifactId> |
91 | + <version>1.8.3</version> | |
54 | 92 | </dependency> |
55 | 93 | <dependency> |
56 | 94 | <groupId>com.alibaba.csp</groupId> |
57 | 95 | <artifactId>sentinel-parameter-flow-control</artifactId> |
96 | + <version>1.8.3</version> | |
97 | + <exclusions> | |
98 | + <exclusion> | |
99 | + <artifactId>sentinel-core</artifactId> | |
100 | + <groupId>com.alibaba.csp</groupId> | |
101 | + </exclusion> | |
102 | + </exclusions> | |
58 | 103 | </dependency> |
59 | 104 | <dependency> |
60 | 105 | <groupId>com.alibaba.csp</groupId> |
61 | 106 | <artifactId>sentinel-api-gateway-adapter-common</artifactId> |
107 | + <version>1.8.3</version> | |
108 | + <exclusions> | |
109 | + <exclusion> | |
110 | + <artifactId>sentinel-parameter-flow-control</artifactId> | |
111 | + <groupId>com.alibaba.csp</groupId> | |
112 | + </exclusion> | |
113 | + <exclusion> | |
114 | + <artifactId>sentinel-core</artifactId> | |
115 | + <groupId>com.alibaba.csp</groupId> | |
116 | + </exclusion> | |
117 | + </exclusions> | |
62 | 118 | </dependency> |
63 | 119 | <dependency> |
64 | 120 | <groupId>org.springframework.boot</groupId> |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/JeecgSentinelDashboardApplication.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/JeecgSentinelApplication.java
... | ... | @@ -29,12 +29,12 @@ import lombok.extern.slf4j.Slf4j; |
29 | 29 | */ |
30 | 30 | @SpringBootApplication |
31 | 31 | @Slf4j |
32 | -public class JeecgSentinelDashboardApplication { | |
32 | +public class JeecgSentinelApplication { | |
33 | 33 | |
34 | 34 | public static void main(String[] args) { |
35 | 35 | System.setProperty("csp.sentinel.app.type", "1"); |
36 | 36 | triggerSentinelInit(); |
37 | - ConfigurableApplicationContext application = SpringApplication.run(JeecgSentinelDashboardApplication.class, args); | |
37 | + ConfigurableApplicationContext application = SpringApplication.run(JeecgSentinelApplication.class, args); | |
38 | 38 | Environment env = application.getEnvironment(); |
39 | 39 | String port = env.getProperty("server.port"); |
40 | 40 | log.info("\n----------------------------------------------------------\n\t" + |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/constants/SentinelConStants.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.constants; | |
2 | + | |
3 | +/** | |
4 | + * sentinel常量配置 | |
5 | + * @author zyf | |
6 | + */ | |
7 | +public class SentinelConStants { | |
8 | + public static final String GROUP_ID = "SENTINEL_GROUP"; | |
9 | + | |
10 | + /** | |
11 | + * 流控规则 | |
12 | + */ | |
13 | + public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules"; | |
14 | + /** | |
15 | + * 热点参数 | |
16 | + */ | |
17 | + public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules"; | |
18 | + /** | |
19 | + * 降级规则 | |
20 | + */ | |
21 | + public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules"; | |
22 | + /** | |
23 | + * 系统规则 | |
24 | + */ | |
25 | + public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules"; | |
26 | + /** | |
27 | + * 授权规则 | |
28 | + */ | |
29 | + public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules"; | |
30 | + | |
31 | + /** | |
32 | + * 网关API | |
33 | + */ | |
34 | + public static final String GETEWAY_API_DATA_ID_POSTFIX = "-api-rules"; | |
35 | + /** | |
36 | + * 网关流控规则 | |
37 | + */ | |
38 | + public static final String GETEWAY_FLOW_DATA_ID_POSTFIX = "-flow-rules"; | |
39 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller; | |
2 | + | |
3 | + | |
4 | +import java.util.Date; | |
5 | +import java.util.List; | |
6 | + | |
7 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
8 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; | |
9 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
10 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
11 | +import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |
12 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
13 | + | |
14 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; | |
15 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
16 | +import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | |
17 | + | |
18 | +import org.slf4j.Logger; | |
19 | +import org.slf4j.LoggerFactory; | |
20 | +import org.springframework.beans.factory.annotation.Autowired; | |
21 | +import org.springframework.beans.factory.annotation.Qualifier; | |
22 | +import org.springframework.web.bind.annotation.DeleteMapping; | |
23 | +import org.springframework.web.bind.annotation.GetMapping; | |
24 | +import org.springframework.web.bind.annotation.PathVariable; | |
25 | +import org.springframework.web.bind.annotation.PostMapping; | |
26 | +import org.springframework.web.bind.annotation.PutMapping; | |
27 | +import org.springframework.web.bind.annotation.RequestBody; | |
28 | +import org.springframework.web.bind.annotation.RequestMapping; | |
29 | +import org.springframework.web.bind.annotation.RequestParam; | |
30 | +import org.springframework.web.bind.annotation.RestController; | |
31 | + | |
32 | +/** | |
33 | + * 授权规则控制器 | |
34 | + * | |
35 | + * @author zyf | |
36 | + * @date 2022-04-13 | |
37 | + */ | |
38 | +@RestController | |
39 | +@RequestMapping(value = "/authority") | |
40 | +public class AuthorityRuleController extends BaseRuleController{ | |
41 | + | |
42 | + private final Logger logger = LoggerFactory.getLogger(AuthorityRuleController.class); | |
43 | + | |
44 | + @Autowired | |
45 | + private RuleRepository<AuthorityRuleEntity, Long> repository; | |
46 | + @Autowired | |
47 | + @Qualifier("authorityRuleNacosProvider") | |
48 | + private DynamicRuleProvider<List<AuthorityRuleEntity>> ruleProvider; | |
49 | + @Autowired | |
50 | + @Qualifier("authorityRuleNacosPublisher") | |
51 | + private DynamicRulePublisher<List<AuthorityRuleEntity>> rulePublisher; | |
52 | + | |
53 | + @GetMapping("/rules") | |
54 | + @AuthAction(PrivilegeType.READ_RULE) | |
55 | + public Result<List<AuthorityRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, | |
56 | + @RequestParam String ip, | |
57 | + @RequestParam Integer port) { | |
58 | + if (StringUtil.isEmpty(app)) { | |
59 | + return Result.ofFail(-1, "app cannot be null or empty"); | |
60 | + } | |
61 | + if (StringUtil.isEmpty(ip)) { | |
62 | + return Result.ofFail(-1, "ip cannot be null or empty"); | |
63 | + } | |
64 | + if (port == null || port <= 0) { | |
65 | + return Result.ofFail(-1, "Invalid parameter: port"); | |
66 | + } | |
67 | + try { | |
68 | + List<AuthorityRuleEntity> rules = ruleProvider.getRules(app); | |
69 | + rules = repository.saveAll(rules); | |
70 | + return Result.ofSuccess(rules); | |
71 | + } catch (Throwable throwable) { | |
72 | + logger.error("Error when querying authority rules", throwable); | |
73 | + return Result.ofFail(-1, throwable.getMessage()); | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + private <R> Result<R> checkEntityInternal(AuthorityRuleEntity entity) { | |
78 | + if (entity == null) { | |
79 | + return Result.ofFail(-1, "bad rule body"); | |
80 | + } | |
81 | + if (StringUtil.isBlank(entity.getApp())) { | |
82 | + return Result.ofFail(-1, "app can't be null or empty"); | |
83 | + } | |
84 | + if (StringUtil.isBlank(entity.getIp())) { | |
85 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
86 | + } | |
87 | + if (entity.getPort() == null || entity.getPort() <= 0) { | |
88 | + return Result.ofFail(-1, "port can't be null"); | |
89 | + } | |
90 | + if (entity.getRule() == null) { | |
91 | + return Result.ofFail(-1, "rule can't be null"); | |
92 | + } | |
93 | + if (StringUtil.isBlank(entity.getResource())) { | |
94 | + return Result.ofFail(-1, "resource name cannot be null or empty"); | |
95 | + } | |
96 | + if (StringUtil.isBlank(entity.getLimitApp())) { | |
97 | + return Result.ofFail(-1, "limitApp should be valid"); | |
98 | + } | |
99 | + if (entity.getStrategy() != RuleConstant.AUTHORITY_WHITE | |
100 | + && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) { | |
101 | + return Result.ofFail(-1, "Unknown strategy (must be blacklist or whitelist)"); | |
102 | + } | |
103 | + return null; | |
104 | + } | |
105 | + | |
106 | + @PostMapping("/rule") | |
107 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
108 | + public Result<AuthorityRuleEntity> apiAddAuthorityRule(@RequestBody AuthorityRuleEntity entity) { | |
109 | + Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); | |
110 | + if (checkResult != null) { | |
111 | + return checkResult; | |
112 | + } | |
113 | + entity.setId(null); | |
114 | + Date date = new Date(); | |
115 | + entity.setGmtCreate(date); | |
116 | + entity.setGmtModified(date); | |
117 | + try { | |
118 | + entity = repository.save(entity); | |
119 | + publishRules(entity.getApp()); | |
120 | + } catch (Throwable throwable) { | |
121 | + logger.error("Failed to add authority rule", throwable); | |
122 | + return Result.ofThrowable(-1, throwable); | |
123 | + } | |
124 | + return Result.ofSuccess(entity); | |
125 | + } | |
126 | + | |
127 | + @PutMapping("/rule/{id}") | |
128 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
129 | + public Result<AuthorityRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, | |
130 | + @RequestBody AuthorityRuleEntity entity) { | |
131 | + if (id == null || id <= 0) { | |
132 | + return Result.ofFail(-1, "Invalid id"); | |
133 | + } | |
134 | + Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); | |
135 | + if (checkResult != null) { | |
136 | + return checkResult; | |
137 | + } | |
138 | + entity.setId(id); | |
139 | + Date date = new Date(); | |
140 | + entity.setGmtCreate(null); | |
141 | + entity.setGmtModified(date); | |
142 | + try { | |
143 | + entity = repository.save(entity); | |
144 | + if (entity == null) { | |
145 | + return Result.ofFail(-1, "Failed to save authority rule"); | |
146 | + } | |
147 | + publishRules(entity.getApp()); | |
148 | + } catch (Throwable throwable) { | |
149 | + logger.error("Failed to save authority rule", throwable); | |
150 | + return Result.ofThrowable(-1, throwable); | |
151 | + } | |
152 | + return Result.ofSuccess(entity); | |
153 | + } | |
154 | + | |
155 | + @DeleteMapping("/rule/{id}") | |
156 | + @AuthAction(PrivilegeType.DELETE_RULE) | |
157 | + public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |
158 | + if (id == null) { | |
159 | + return Result.ofFail(-1, "id cannot be null"); | |
160 | + } | |
161 | + AuthorityRuleEntity oldEntity = repository.findById(id); | |
162 | + if (oldEntity == null) { | |
163 | + return Result.ofSuccess(null); | |
164 | + } | |
165 | + try { | |
166 | + repository.delete(id); | |
167 | + publishRules(oldEntity.getApp()); | |
168 | + } catch (Exception e) { | |
169 | + return Result.ofFail(-1, e.getMessage()); | |
170 | + } | |
171 | + return Result.ofSuccess(id); | |
172 | + } | |
173 | + | |
174 | + private void publishRules(String app) throws Exception { | |
175 | + List<AuthorityRuleEntity> rules = repository.findAllByApp(app); | |
176 | + rulePublisher.publish(app, rules); | |
177 | + //延迟加载 | |
178 | + delayTime(); | |
179 | + } | |
180 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller; | |
2 | + | |
3 | + | |
4 | +import java.util.Date; | |
5 | +import java.util.List; | |
6 | + | |
7 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
8 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; | |
9 | +import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | |
10 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
11 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
12 | +import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |
13 | +import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy; | |
14 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
15 | + | |
16 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; | |
17 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
18 | + | |
19 | +import org.slf4j.Logger; | |
20 | +import org.slf4j.LoggerFactory; | |
21 | +import org.springframework.beans.factory.annotation.Autowired; | |
22 | +import org.springframework.beans.factory.annotation.Qualifier; | |
23 | +import org.springframework.web.bind.annotation.DeleteMapping; | |
24 | +import org.springframework.web.bind.annotation.GetMapping; | |
25 | +import org.springframework.web.bind.annotation.PathVariable; | |
26 | +import org.springframework.web.bind.annotation.PostMapping; | |
27 | +import org.springframework.web.bind.annotation.PutMapping; | |
28 | +import org.springframework.web.bind.annotation.RequestBody; | |
29 | +import org.springframework.web.bind.annotation.RequestMapping; | |
30 | +import org.springframework.web.bind.annotation.RestController; | |
31 | + | |
32 | +/** | |
33 | + * 降级规则控制器 | |
34 | + * | |
35 | + * @author zyf | |
36 | + * @date 2022-04-13 | |
37 | + */ | |
38 | +@RestController | |
39 | +@RequestMapping("/degrade") | |
40 | +public class DegradeController extends BaseRuleController{ | |
41 | + | |
42 | + private final Logger logger = LoggerFactory.getLogger(DegradeController.class); | |
43 | + | |
44 | + @Autowired | |
45 | + private RuleRepository<DegradeRuleEntity, Long> repository; | |
46 | + @Autowired | |
47 | + @Qualifier("degradeRuleNacosProvider") | |
48 | + private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider; | |
49 | + @Autowired | |
50 | + @Qualifier("degradeRuleNacosPublisher") | |
51 | + private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher; | |
52 | + | |
53 | + @GetMapping("/rules.json") | |
54 | + @AuthAction(PrivilegeType.READ_RULE) | |
55 | + public Result<List<DegradeRuleEntity>> apiQueryMachineRules(String app, String ip, Integer port) { | |
56 | + if (StringUtil.isEmpty(app)) { | |
57 | + return Result.ofFail(-1, "app can't be null or empty"); | |
58 | + } | |
59 | + if (StringUtil.isEmpty(ip)) { | |
60 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
61 | + } | |
62 | + if (port == null) { | |
63 | + return Result.ofFail(-1, "port can't be null"); | |
64 | + } | |
65 | + try { | |
66 | + List<DegradeRuleEntity> rules = ruleProvider.getRules(app); | |
67 | + rules = repository.saveAll(rules); | |
68 | + return Result.ofSuccess(rules); | |
69 | + } catch (Throwable throwable) { | |
70 | + logger.error("queryApps error:", throwable); | |
71 | + return Result.ofThrowable(-1, throwable); | |
72 | + } | |
73 | + } | |
74 | + | |
75 | + @PostMapping("/rule") | |
76 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
77 | + public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) { | |
78 | + Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity); | |
79 | + if (checkResult != null) { | |
80 | + return checkResult; | |
81 | + } | |
82 | + Date date = new Date(); | |
83 | + entity.setGmtCreate(date); | |
84 | + entity.setGmtModified(date); | |
85 | + try { | |
86 | + entity = repository.save(entity); | |
87 | + publishRules(entity.getApp()); | |
88 | + } catch (Throwable t) { | |
89 | + logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t); | |
90 | + return Result.ofThrowable(-1, t); | |
91 | + } | |
92 | + return Result.ofSuccess(entity); | |
93 | + } | |
94 | + | |
95 | + @PutMapping("/rule/{id}") | |
96 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
97 | + public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id, | |
98 | + @RequestBody DegradeRuleEntity entity) { | |
99 | + if (id == null || id <= 0) { | |
100 | + return Result.ofFail(-1, "id can't be null or negative"); | |
101 | + } | |
102 | + DegradeRuleEntity oldEntity = repository.findById(id); | |
103 | + if (oldEntity == null) { | |
104 | + return Result.ofFail(-1, "Degrade rule does not exist, id=" + id); | |
105 | + } | |
106 | + entity.setApp(oldEntity.getApp()); | |
107 | + entity.setIp(oldEntity.getIp()); | |
108 | + entity.setPort(oldEntity.getPort()); | |
109 | + entity.setId(oldEntity.getId()); | |
110 | + Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity); | |
111 | + if (checkResult != null) { | |
112 | + return checkResult; | |
113 | + } | |
114 | + | |
115 | + entity.setGmtCreate(oldEntity.getGmtCreate()); | |
116 | + entity.setGmtModified(new Date()); | |
117 | + try { | |
118 | + entity = repository.save(entity); | |
119 | + publishRules(entity.getApp()); | |
120 | + } catch (Throwable t) { | |
121 | + logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t); | |
122 | + return Result.ofThrowable(-1, t); | |
123 | + } | |
124 | + return Result.ofSuccess(entity); | |
125 | + } | |
126 | + | |
127 | + @DeleteMapping("/rule/{id}") | |
128 | + @AuthAction(PrivilegeType.DELETE_RULE) | |
129 | + public Result<Long> delete(@PathVariable("id") Long id) { | |
130 | + if (id == null) { | |
131 | + return Result.ofFail(-1, "id can't be null"); | |
132 | + } | |
133 | + | |
134 | + DegradeRuleEntity oldEntity = repository.findById(id); | |
135 | + if (oldEntity == null) { | |
136 | + return Result.ofSuccess(null); | |
137 | + } | |
138 | + | |
139 | + try { | |
140 | + repository.delete(id); | |
141 | + publishRules(oldEntity.getApp()); | |
142 | + } catch (Throwable throwable) { | |
143 | + logger.error("Failed to delete degrade rule, id={}", id, throwable); | |
144 | + return Result.ofThrowable(-1, throwable); | |
145 | + } | |
146 | + return Result.ofSuccess(id); | |
147 | + } | |
148 | + | |
149 | + private void publishRules(/*@NonNull*/ String app) throws Exception { | |
150 | + List<DegradeRuleEntity> rules = repository.findAllByApp(app); | |
151 | + rulePublisher.publish(app, rules); | |
152 | + //延迟加载 | |
153 | + delayTime(); | |
154 | + } | |
155 | + | |
156 | + private <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) { | |
157 | + if (StringUtil.isBlank(entity.getApp())) { | |
158 | + return Result.ofFail(-1, "app can't be blank"); | |
159 | + } | |
160 | + if (StringUtil.isBlank(entity.getIp())) { | |
161 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
162 | + } | |
163 | + if (entity.getPort() == null || entity.getPort() <= 0) { | |
164 | + return Result.ofFail(-1, "invalid port: " + entity.getPort()); | |
165 | + } | |
166 | + if (StringUtil.isBlank(entity.getLimitApp())) { | |
167 | + return Result.ofFail(-1, "limitApp can't be null or empty"); | |
168 | + } | |
169 | + if (StringUtil.isBlank(entity.getResource())) { | |
170 | + return Result.ofFail(-1, "resource can't be null or empty"); | |
171 | + } | |
172 | + Double threshold = entity.getCount(); | |
173 | + if (threshold == null || threshold < 0) { | |
174 | + return Result.ofFail(-1, "invalid threshold: " + threshold); | |
175 | + } | |
176 | + Integer recoveryTimeoutSec = entity.getTimeWindow(); | |
177 | + if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) { | |
178 | + return Result.ofFail(-1, "recoveryTimeout should be positive"); | |
179 | + } | |
180 | + Integer strategy = entity.getGrade(); | |
181 | + if (strategy == null) { | |
182 | + return Result.ofFail(-1, "circuit breaker strategy cannot be null"); | |
183 | + } | |
184 | + if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType() | |
185 | + || strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) { | |
186 | + return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy); | |
187 | + } | |
188 | + if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount() <= 0) { | |
189 | + return Result.ofFail(-1, "Invalid minRequestAmount"); | |
190 | + } | |
191 | + if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) { | |
192 | + return Result.ofFail(-1, "Invalid statInterval"); | |
193 | + } | |
194 | + if (strategy == RuleConstant.DEGRADE_GRADE_RT) { | |
195 | + Double slowRatio = entity.getSlowRatioThreshold(); | |
196 | + if (slowRatio == null) { | |
197 | + return Result.ofFail(-1, "SlowRatioThreshold is required for slow request ratio strategy"); | |
198 | + } else if (slowRatio < 0 || slowRatio > 1) { | |
199 | + return Result.ofFail(-1, "SlowRatioThreshold should be in range: [0.0, 1.0]"); | |
200 | + } | |
201 | + } else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) { | |
202 | + if (threshold > 1) { | |
203 | + return Result.ofFail(-1, "Ratio threshold should be in range: [0.0, 1.0]"); | |
204 | + } | |
205 | + } | |
206 | + return null; | |
207 | + } | |
208 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller; | |
2 | + | |
3 | + | |
4 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
5 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService; | |
6 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; | |
7 | +import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException; | |
8 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion; | |
9 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; | |
10 | +import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement; | |
11 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
12 | +import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | |
13 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
14 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
15 | +import com.alibaba.csp.sentinel.dashboard.util.VersionUtils; | |
16 | +import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |
17 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
18 | +import org.slf4j.Logger; | |
19 | +import org.slf4j.LoggerFactory; | |
20 | +import org.springframework.beans.factory.annotation.Autowired; | |
21 | +import org.springframework.beans.factory.annotation.Qualifier; | |
22 | +import org.springframework.web.bind.annotation.*; | |
23 | + | |
24 | +import java.util.Date; | |
25 | +import java.util.List; | |
26 | +import java.util.Optional; | |
27 | +import java.util.concurrent.ExecutionException; | |
28 | + | |
29 | +/** | |
30 | + * 热点参数规则控制器 | |
31 | + * | |
32 | + * @author zyf | |
33 | + * @date 2022-04-13 | |
34 | + */ | |
35 | +@RestController | |
36 | +@RequestMapping(value = "/paramFlow") | |
37 | +public class ParamFlowRuleController extends BaseRuleController{ | |
38 | + | |
39 | + private final Logger logger = LoggerFactory.getLogger(ParamFlowRuleController.class); | |
40 | + | |
41 | + @Autowired | |
42 | + private AppManagement appManagement; | |
43 | + @Autowired | |
44 | + private RuleRepository<ParamFlowRuleEntity, Long> repository; | |
45 | + @Autowired | |
46 | + @Qualifier("paramFlowRuleNacosProvider") | |
47 | + private DynamicRuleProvider<List<ParamFlowRuleEntity>> ruleProvider; | |
48 | + @Autowired | |
49 | + @Qualifier("paramFlowRuleNacosPublisher") | |
50 | + private DynamicRulePublisher<List<ParamFlowRuleEntity>> rulePublisher; | |
51 | + | |
52 | + private boolean checkIfSupported(String app, String ip, int port) { | |
53 | + try { | |
54 | + return Optional.ofNullable(appManagement.getDetailApp(app)) | |
55 | + .flatMap(e -> e.getMachine(ip, port)) | |
56 | + .flatMap(m -> VersionUtils.parseVersion(m.getVersion()) | |
57 | + .map(v -> v.greaterOrEqual(version020))) | |
58 | + .orElse(true); | |
59 | + // If error occurred or cannot retrieve machine info, return true. | |
60 | + } catch (Exception ex) { | |
61 | + return true; | |
62 | + } | |
63 | + } | |
64 | + | |
65 | + @GetMapping("/rules") | |
66 | + @AuthAction(PrivilegeType.READ_RULE) | |
67 | + public Result<List<ParamFlowRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, | |
68 | + @RequestParam String ip, | |
69 | + @RequestParam Integer port) { | |
70 | + if (StringUtil.isEmpty(app)) { | |
71 | + return Result.ofFail(-1, "app cannot be null or empty"); | |
72 | + } | |
73 | + if (StringUtil.isEmpty(ip)) { | |
74 | + return Result.ofFail(-1, "ip cannot be null or empty"); | |
75 | + } | |
76 | + if (port == null || port <= 0) { | |
77 | + return Result.ofFail(-1, "Invalid parameter: port"); | |
78 | + } | |
79 | + if (!checkIfSupported(app, ip, port)) { | |
80 | + return unsupportedVersion(); | |
81 | + } | |
82 | + try { | |
83 | + List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app); | |
84 | + rules = repository.saveAll(rules); | |
85 | + return Result.ofSuccess(rules); | |
86 | + } catch (ExecutionException ex) { | |
87 | + logger.error("Error when querying parameter flow rules", ex.getCause()); | |
88 | + if (isNotSupported(ex.getCause())) { | |
89 | + return unsupportedVersion(); | |
90 | + } else { | |
91 | + return Result.ofThrowable(-1, ex.getCause()); | |
92 | + } | |
93 | + } catch (Throwable throwable) { | |
94 | + logger.error("Error when querying parameter flow rules", throwable); | |
95 | + return Result.ofFail(-1, throwable.getMessage()); | |
96 | + } | |
97 | + } | |
98 | + | |
99 | + private boolean isNotSupported(Throwable ex) { | |
100 | + return ex instanceof CommandNotFoundException; | |
101 | + } | |
102 | + | |
103 | + @PostMapping("/rule") | |
104 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
105 | + public Result<ParamFlowRuleEntity> apiAddParamFlowRule(@RequestBody ParamFlowRuleEntity entity) { | |
106 | + Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | |
107 | + if (checkResult != null) { | |
108 | + return checkResult; | |
109 | + } | |
110 | + if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) { | |
111 | + return unsupportedVersion(); | |
112 | + } | |
113 | + entity.setId(null); | |
114 | + entity.getRule().setResource(entity.getResource().trim()); | |
115 | + Date date = new Date(); | |
116 | + entity.setGmtCreate(date); | |
117 | + entity.setGmtModified(date); | |
118 | + try { | |
119 | + entity = repository.save(entity); | |
120 | + publishRules(entity.getApp()); | |
121 | + return Result.ofSuccess(entity); | |
122 | + } catch (ExecutionException ex) { | |
123 | + logger.error("Error when adding new parameter flow rules", ex.getCause()); | |
124 | + if (isNotSupported(ex.getCause())) { | |
125 | + return unsupportedVersion(); | |
126 | + } else { | |
127 | + return Result.ofThrowable(-1, ex.getCause()); | |
128 | + } | |
129 | + } catch (Throwable throwable) { | |
130 | + logger.error("Error when adding new parameter flow rules", throwable); | |
131 | + return Result.ofFail(-1, throwable.getMessage()); | |
132 | + } | |
133 | + } | |
134 | + | |
135 | + private <R> Result<R> checkEntityInternal(ParamFlowRuleEntity entity) { | |
136 | + if (entity == null) { | |
137 | + return Result.ofFail(-1, "bad rule body"); | |
138 | + } | |
139 | + if (StringUtil.isBlank(entity.getApp())) { | |
140 | + return Result.ofFail(-1, "app can't be null or empty"); | |
141 | + } | |
142 | + if (StringUtil.isBlank(entity.getIp())) { | |
143 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
144 | + } | |
145 | + if (entity.getPort() == null || entity.getPort() <= 0) { | |
146 | + return Result.ofFail(-1, "port can't be null"); | |
147 | + } | |
148 | + if (entity.getRule() == null) { | |
149 | + return Result.ofFail(-1, "rule can't be null"); | |
150 | + } | |
151 | + if (StringUtil.isBlank(entity.getResource())) { | |
152 | + return Result.ofFail(-1, "resource name cannot be null or empty"); | |
153 | + } | |
154 | + if (entity.getCount() < 0) { | |
155 | + return Result.ofFail(-1, "count should be valid"); | |
156 | + } | |
157 | + if (entity.getGrade() != RuleConstant.FLOW_GRADE_QPS) { | |
158 | + return Result.ofFail(-1, "Unknown mode (blockGrade) for parameter flow control"); | |
159 | + } | |
160 | + if (entity.getParamIdx() == null || entity.getParamIdx() < 0) { | |
161 | + return Result.ofFail(-1, "paramIdx should be valid"); | |
162 | + } | |
163 | + if (entity.getDurationInSec() <= 0) { | |
164 | + return Result.ofFail(-1, "durationInSec should be valid"); | |
165 | + } | |
166 | + if (entity.getControlBehavior() < 0) { | |
167 | + return Result.ofFail(-1, "controlBehavior should be valid"); | |
168 | + } | |
169 | + return null; | |
170 | + } | |
171 | + | |
172 | + @PutMapping("/rule/{id}") | |
173 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
174 | + public Result<ParamFlowRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, | |
175 | + @RequestBody ParamFlowRuleEntity entity) { | |
176 | + if (id == null || id <= 0) { | |
177 | + return Result.ofFail(-1, "Invalid id"); | |
178 | + } | |
179 | + ParamFlowRuleEntity oldEntity = repository.findById(id); | |
180 | + if (oldEntity == null) { | |
181 | + return Result.ofFail(-1, "id " + id + " does not exist"); | |
182 | + } | |
183 | + | |
184 | + Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | |
185 | + if (checkResult != null) { | |
186 | + return checkResult; | |
187 | + } | |
188 | + if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) { | |
189 | + return unsupportedVersion(); | |
190 | + } | |
191 | + entity.setId(id); | |
192 | + Date date = new Date(); | |
193 | + entity.setGmtCreate(oldEntity.getGmtCreate()); | |
194 | + entity.setGmtModified(date); | |
195 | + try { | |
196 | + entity = repository.save(entity); | |
197 | + publishRules(entity.getApp()); | |
198 | + return Result.ofSuccess(entity); | |
199 | + } catch (ExecutionException ex) { | |
200 | + logger.error("Error when updating parameter flow rules, id=" + id, ex.getCause()); | |
201 | + if (isNotSupported(ex.getCause())) { | |
202 | + return unsupportedVersion(); | |
203 | + } else { | |
204 | + return Result.ofThrowable(-1, ex.getCause()); | |
205 | + } | |
206 | + } catch (Throwable throwable) { | |
207 | + logger.error("Error when updating parameter flow rules, id=" + id, throwable); | |
208 | + return Result.ofFail(-1, throwable.getMessage()); | |
209 | + } | |
210 | + } | |
211 | + | |
212 | + @DeleteMapping("/rule/{id}") | |
213 | + @AuthAction(PrivilegeType.DELETE_RULE) | |
214 | + public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |
215 | + if (id == null) { | |
216 | + return Result.ofFail(-1, "id cannot be null"); | |
217 | + } | |
218 | + ParamFlowRuleEntity oldEntity = repository.findById(id); | |
219 | + if (oldEntity == null) { | |
220 | + return Result.ofSuccess(null); | |
221 | + } | |
222 | + | |
223 | + try { | |
224 | + repository.delete(id); | |
225 | + publishRules(oldEntity.getApp()); | |
226 | + return Result.ofSuccess(id); | |
227 | + } catch (ExecutionException ex) { | |
228 | + logger.error("Error when deleting parameter flow rules", ex.getCause()); | |
229 | + if (isNotSupported(ex.getCause())) { | |
230 | + return unsupportedVersion(); | |
231 | + } else { | |
232 | + return Result.ofThrowable(-1, ex.getCause()); | |
233 | + } | |
234 | + } catch (Throwable throwable) { | |
235 | + logger.error("Error when deleting parameter flow rules", throwable); | |
236 | + return Result.ofFail(-1, throwable.getMessage()); | |
237 | + } | |
238 | + } | |
239 | + | |
240 | + private void publishRules(String app) throws Exception { | |
241 | + List<ParamFlowRuleEntity> rules = repository.findAllByApp(app); | |
242 | + rulePublisher.publish(app, rules); | |
243 | + //延迟加载 | |
244 | + delayTime(); | |
245 | + } | |
246 | + | |
247 | + private <R> Result<R> unsupportedVersion() { | |
248 | + return Result.ofFail(4041, | |
249 | + "Sentinel client not supported for parameter flow control (unsupported version or dependency absent)"); | |
250 | + } | |
251 | + | |
252 | + private final SentinelVersion version020 = new SentinelVersion().setMinorVersion(2); | |
253 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller; | |
2 | + | |
3 | + | |
4 | +import java.util.Date; | |
5 | +import java.util.List; | |
6 | + | |
7 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
8 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; | |
9 | +import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | |
10 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
11 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
12 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
13 | + | |
14 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; | |
15 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
16 | + | |
17 | +import org.slf4j.Logger; | |
18 | +import org.slf4j.LoggerFactory; | |
19 | +import org.springframework.beans.factory.annotation.Autowired; | |
20 | +import org.springframework.beans.factory.annotation.Qualifier; | |
21 | +import org.springframework.web.bind.annotation.GetMapping; | |
22 | +import org.springframework.web.bind.annotation.RequestMapping; | |
23 | +import org.springframework.web.bind.annotation.RestController; | |
24 | + | |
25 | +/** | |
26 | + * 系统规则控制器 | |
27 | + * | |
28 | + * @author zyf | |
29 | + * @date 2022-04-13 | |
30 | + */ | |
31 | +@RestController | |
32 | +@RequestMapping("/system") | |
33 | +public class SystemController extends BaseRuleController{ | |
34 | + | |
35 | + private final Logger logger = LoggerFactory.getLogger(SystemController.class); | |
36 | + | |
37 | + @Autowired | |
38 | + private RuleRepository<SystemRuleEntity, Long> repository; | |
39 | + @Autowired | |
40 | + @Qualifier("systemRuleNacosProvider") | |
41 | + private DynamicRuleProvider<List<SystemRuleEntity>> ruleProvider; | |
42 | + @Autowired | |
43 | + @Qualifier("systemRuleNacosPublisher") | |
44 | + private DynamicRulePublisher<List<SystemRuleEntity>> rulePublisher; | |
45 | + | |
46 | + private <R> Result<R> checkBasicParams(String app, String ip, Integer port) { | |
47 | + if (StringUtil.isEmpty(app)) { | |
48 | + return Result.ofFail(-1, "app can't be null or empty"); | |
49 | + } | |
50 | + if (StringUtil.isEmpty(ip)) { | |
51 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
52 | + } | |
53 | + if (port == null) { | |
54 | + return Result.ofFail(-1, "port can't be null"); | |
55 | + } | |
56 | + if (port <= 0 || port > 65535) { | |
57 | + return Result.ofFail(-1, "port should be in (0, 65535)"); | |
58 | + } | |
59 | + return null; | |
60 | + } | |
61 | + | |
62 | + @GetMapping("/rules.json") | |
63 | + @AuthAction(PrivilegeType.READ_RULE) | |
64 | + public Result<List<SystemRuleEntity>> apiQueryMachineRules(String app, String ip, | |
65 | + Integer port) { | |
66 | + Result<List<SystemRuleEntity>> checkResult = checkBasicParams(app, ip, port); | |
67 | + if (checkResult != null) { | |
68 | + return checkResult; | |
69 | + } | |
70 | + try { | |
71 | + List<SystemRuleEntity> rules = ruleProvider.getRules(app); | |
72 | + rules = repository.saveAll(rules); | |
73 | + return Result.ofSuccess(rules); | |
74 | + } catch (Throwable throwable) { | |
75 | + logger.error("Query machine system rules error", throwable); | |
76 | + return Result.ofThrowable(-1, throwable); | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + private int countNotNullAndNotNegative(Number... values) { | |
81 | + int notNullCount = 0; | |
82 | + for (int i = 0; i < values.length; i++) { | |
83 | + if (values[i] != null && values[i].doubleValue() >= 0) { | |
84 | + notNullCount++; | |
85 | + } | |
86 | + } | |
87 | + return notNullCount; | |
88 | + } | |
89 | + | |
90 | + @RequestMapping("/new.json") | |
91 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
92 | + public Result<SystemRuleEntity> apiAdd(String app, String ip, Integer port, | |
93 | + Double highestSystemLoad, Double highestCpuUsage, Long avgRt, | |
94 | + Long maxThread, Double qps) { | |
95 | + | |
96 | + Result<SystemRuleEntity> checkResult = checkBasicParams(app, ip, port); | |
97 | + if (checkResult != null) { | |
98 | + return checkResult; | |
99 | + } | |
100 | + | |
101 | + int notNullCount = countNotNullAndNotNegative(highestSystemLoad, avgRt, maxThread, qps, highestCpuUsage); | |
102 | + if (notNullCount != 1) { | |
103 | + return Result.ofFail(-1, "only one of [highestSystemLoad, avgRt, maxThread, qps,highestCpuUsage] " | |
104 | + + "value must be set > 0, but " + notNullCount + " values get"); | |
105 | + } | |
106 | + if (null != highestCpuUsage && highestCpuUsage > 1) { | |
107 | + return Result.ofFail(-1, "highestCpuUsage must between [0.0, 1.0]"); | |
108 | + } | |
109 | + SystemRuleEntity entity = new SystemRuleEntity(); | |
110 | + entity.setApp(app.trim()); | |
111 | + entity.setIp(ip.trim()); | |
112 | + entity.setPort(port); | |
113 | + // -1 is a fake value | |
114 | + if (null != highestSystemLoad) { | |
115 | + entity.setHighestSystemLoad(highestSystemLoad); | |
116 | + } else { | |
117 | + entity.setHighestSystemLoad(-1D); | |
118 | + } | |
119 | + | |
120 | + if (null != highestCpuUsage) { | |
121 | + entity.setHighestCpuUsage(highestCpuUsage); | |
122 | + } else { | |
123 | + entity.setHighestCpuUsage(-1D); | |
124 | + } | |
125 | + | |
126 | + if (avgRt != null) { | |
127 | + entity.setAvgRt(avgRt); | |
128 | + } else { | |
129 | + entity.setAvgRt(-1L); | |
130 | + } | |
131 | + if (maxThread != null) { | |
132 | + entity.setMaxThread(maxThread); | |
133 | + } else { | |
134 | + entity.setMaxThread(-1L); | |
135 | + } | |
136 | + if (qps != null) { | |
137 | + entity.setQps(qps); | |
138 | + } else { | |
139 | + entity.setQps(-1D); | |
140 | + } | |
141 | + Date date = new Date(); | |
142 | + entity.setGmtCreate(date); | |
143 | + entity.setGmtModified(date); | |
144 | + try { | |
145 | + entity = repository.save(entity); | |
146 | + publishRules(app); | |
147 | + } catch (Throwable throwable) { | |
148 | + logger.error("Add SystemRule error", throwable); | |
149 | + return Result.ofThrowable(-1, throwable); | |
150 | + } | |
151 | + return Result.ofSuccess(entity); | |
152 | + } | |
153 | + | |
154 | + @GetMapping("/save.json") | |
155 | + @AuthAction(PrivilegeType.WRITE_RULE) | |
156 | + public Result<SystemRuleEntity> apiUpdateIfNotNull(Long id, String app, Double highestSystemLoad, | |
157 | + Double highestCpuUsage, Long avgRt, Long maxThread, Double qps) { | |
158 | + if (id == null) { | |
159 | + return Result.ofFail(-1, "id can't be null"); | |
160 | + } | |
161 | + SystemRuleEntity entity = repository.findById(id); | |
162 | + if (entity == null) { | |
163 | + return Result.ofFail(-1, "id " + id + " dose not exist"); | |
164 | + } | |
165 | + | |
166 | + if (StringUtil.isNotBlank(app)) { | |
167 | + entity.setApp(app.trim()); | |
168 | + } | |
169 | + if (highestSystemLoad != null) { | |
170 | + if (highestSystemLoad < 0) { | |
171 | + return Result.ofFail(-1, "highestSystemLoad must >= 0"); | |
172 | + } | |
173 | + entity.setHighestSystemLoad(highestSystemLoad); | |
174 | + } | |
175 | + if (highestCpuUsage != null) { | |
176 | + if (highestCpuUsage < 0) { | |
177 | + return Result.ofFail(-1, "highestCpuUsage must >= 0"); | |
178 | + } | |
179 | + if (highestCpuUsage > 1) { | |
180 | + return Result.ofFail(-1, "highestCpuUsage must <= 1"); | |
181 | + } | |
182 | + entity.setHighestCpuUsage(highestCpuUsage); | |
183 | + } | |
184 | + if (avgRt != null) { | |
185 | + if (avgRt < 0) { | |
186 | + return Result.ofFail(-1, "avgRt must >= 0"); | |
187 | + } | |
188 | + entity.setAvgRt(avgRt); | |
189 | + } | |
190 | + if (maxThread != null) { | |
191 | + if (maxThread < 0) { | |
192 | + return Result.ofFail(-1, "maxThread must >= 0"); | |
193 | + } | |
194 | + entity.setMaxThread(maxThread); | |
195 | + } | |
196 | + if (qps != null) { | |
197 | + if (qps < 0) { | |
198 | + return Result.ofFail(-1, "qps must >= 0"); | |
199 | + } | |
200 | + entity.setQps(qps); | |
201 | + } | |
202 | + Date date = new Date(); | |
203 | + entity.setGmtModified(date); | |
204 | + try { | |
205 | + entity = repository.save(entity); | |
206 | + publishRules(entity.getApp()); | |
207 | + } catch (Throwable throwable) { | |
208 | + logger.error("save error:", throwable); | |
209 | + return Result.ofThrowable(-1, throwable); | |
210 | + } | |
211 | + return Result.ofSuccess(entity); | |
212 | + } | |
213 | + | |
214 | + @RequestMapping("/delete.json") | |
215 | + @AuthAction(PrivilegeType.DELETE_RULE) | |
216 | + public Result<?> delete(Long id) { | |
217 | + if (id == null) { | |
218 | + return Result.ofFail(-1, "id can't be null"); | |
219 | + } | |
220 | + SystemRuleEntity oldEntity = repository.findById(id); | |
221 | + if (oldEntity == null) { | |
222 | + return Result.ofSuccess(null); | |
223 | + } | |
224 | + try { | |
225 | + repository.delete(id); | |
226 | + publishRules(oldEntity.getApp()); | |
227 | + } catch (Throwable throwable) { | |
228 | + logger.error("delete error:", throwable); | |
229 | + return Result.ofThrowable(-1, throwable); | |
230 | + } | |
231 | + return Result.ofSuccess(id); | |
232 | + } | |
233 | + | |
234 | + private void publishRules(String app) throws Exception { | |
235 | + List<SystemRuleEntity> rules = repository.findAllByApp(app); | |
236 | + rulePublisher.publish(app, rules); | |
237 | + //延迟加载 | |
238 | + delayTime(); | |
239 | + } | |
240 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/base/BaseRuleController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller; | |
2 | + | |
3 | +import java.util.concurrent.TimeUnit; | |
4 | + | |
5 | + | |
6 | +/** | |
7 | + * Nacos持久化通用处理类 | |
8 | + * | |
9 | + * @author zyf | |
10 | + * @date 2022-04-13 | |
11 | + */ | |
12 | +public class BaseRuleController { | |
13 | + /** | |
14 | + * 延迟一下 | |
15 | + * | |
16 | + * 解释:列表加载数据的时候,Nacos持久化还没做完,导致加载数据不对 | |
17 | + */ | |
18 | + public static void delayTime(){ | |
19 | + try { | |
20 | + TimeUnit.MILLISECONDS.sleep(100); | |
21 | + System.out.println("-------------睡100毫秒-----------"); | |
22 | + } catch (InterruptedException e) { | |
23 | + e.printStackTrace(); | |
24 | + } | |
25 | + } | |
26 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller.gateway; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
4 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService; | |
5 | +import com.alibaba.csp.sentinel.dashboard.controller.BaseRuleController; | |
6 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | |
7 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiPredicateItemEntity; | |
8 | +import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | |
9 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
10 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.AddApiReqVo; | |
11 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.ApiPredicateItemVo; | |
12 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.UpdateApiReqVo; | |
13 | +import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemApiDefinitionStore; | |
14 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
15 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
16 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
17 | +import org.slf4j.Logger; | |
18 | +import org.slf4j.LoggerFactory; | |
19 | +import org.springframework.beans.factory.annotation.Autowired; | |
20 | +import org.springframework.beans.factory.annotation.Qualifier; | |
21 | +import org.springframework.util.CollectionUtils; | |
22 | +import org.springframework.web.bind.annotation.*; | |
23 | + | |
24 | +import javax.servlet.http.HttpServletRequest; | |
25 | +import java.util.*; | |
26 | + | |
27 | +import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*; | |
28 | + | |
29 | +/** | |
30 | + * 网关API规则控制器 | |
31 | + * | |
32 | + * @author zyf | |
33 | + * @date 2022-04-13 | |
34 | + */ | |
35 | +@RestController | |
36 | +@RequestMapping(value = "/gateway/api") | |
37 | +public class GatewayApiController extends BaseRuleController { | |
38 | + | |
39 | + private final Logger logger = LoggerFactory.getLogger(GatewayApiController.class); | |
40 | + | |
41 | + @Autowired | |
42 | + private InMemApiDefinitionStore repository; | |
43 | + | |
44 | + | |
45 | + @Autowired | |
46 | + @Qualifier("gateWayApiNacosProvider") | |
47 | + private DynamicRuleProvider<List<ApiDefinitionEntity>> apiProvider; | |
48 | + | |
49 | + @Autowired | |
50 | + @Qualifier("gateWayApiNacosPublisher") | |
51 | + private DynamicRulePublisher<List<ApiDefinitionEntity>> apiPublisher; | |
52 | + | |
53 | + @GetMapping("/list.json") | |
54 | + @AuthAction(AuthService.PrivilegeType.READ_RULE) | |
55 | + public Result<List<ApiDefinitionEntity>> queryApis(String app, String ip, Integer port) { | |
56 | + if (StringUtil.isEmpty(app)) { | |
57 | + return Result.ofFail(-1, "app can't be null or empty"); | |
58 | + } | |
59 | + if (StringUtil.isEmpty(ip)) { | |
60 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
61 | + } | |
62 | + if (port == null) { | |
63 | + return Result.ofFail(-1, "port can't be null"); | |
64 | + } | |
65 | + | |
66 | + try { | |
67 | + List<ApiDefinitionEntity> apis = apiProvider.getRules(app); | |
68 | + repository.saveAll(apis); | |
69 | + return Result.ofSuccess(apis); | |
70 | + } catch (Throwable throwable) { | |
71 | + logger.error("queryApis error:", throwable); | |
72 | + return Result.ofThrowable(-1, throwable); | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + @PostMapping("/new.json") | |
77 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
78 | + public Result<ApiDefinitionEntity> addApi(HttpServletRequest request, @RequestBody AddApiReqVo reqVo) { | |
79 | + | |
80 | + String app = reqVo.getApp(); | |
81 | + if (StringUtil.isBlank(app)) { | |
82 | + return Result.ofFail(-1, "app can't be null or empty"); | |
83 | + } | |
84 | + | |
85 | + ApiDefinitionEntity entity = new ApiDefinitionEntity(); | |
86 | + entity.setApp(app.trim()); | |
87 | + | |
88 | + String ip = reqVo.getIp(); | |
89 | + if (StringUtil.isBlank(ip)) { | |
90 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
91 | + } | |
92 | + entity.setIp(ip.trim()); | |
93 | + | |
94 | + Integer port = reqVo.getPort(); | |
95 | + if (port == null) { | |
96 | + return Result.ofFail(-1, "port can't be null"); | |
97 | + } | |
98 | + entity.setPort(port); | |
99 | + | |
100 | + // API名称 | |
101 | + String apiName = reqVo.getApiName(); | |
102 | + if (StringUtil.isBlank(apiName)) { | |
103 | + return Result.ofFail(-1, "apiName can't be null or empty"); | |
104 | + } | |
105 | + entity.setApiName(apiName.trim()); | |
106 | + | |
107 | + // 匹配规则列表 | |
108 | + List<ApiPredicateItemVo> predicateItems = reqVo.getPredicateItems(); | |
109 | + if (CollectionUtils.isEmpty(predicateItems)) { | |
110 | + return Result.ofFail(-1, "predicateItems can't empty"); | |
111 | + } | |
112 | + | |
113 | + List<ApiPredicateItemEntity> predicateItemEntities = new ArrayList<>(); | |
114 | + for (ApiPredicateItemVo predicateItem : predicateItems) { | |
115 | + ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity(); | |
116 | + | |
117 | + // 匹配模式 | |
118 | + Integer matchStrategy = predicateItem.getMatchStrategy(); | |
119 | + if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) { | |
120 | + return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy); | |
121 | + } | |
122 | + predicateItemEntity.setMatchStrategy(matchStrategy); | |
123 | + | |
124 | + // 匹配串 | |
125 | + String pattern = predicateItem.getPattern(); | |
126 | + if (StringUtil.isBlank(pattern)) { | |
127 | + return Result.ofFail(-1, "pattern can't be null or empty"); | |
128 | + } | |
129 | + predicateItemEntity.setPattern(pattern); | |
130 | + | |
131 | + predicateItemEntities.add(predicateItemEntity); | |
132 | + } | |
133 | + entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities)); | |
134 | + | |
135 | + // 检查API名称不能重复 | |
136 | + List<ApiDefinitionEntity> allApis = repository.findAllByMachine(MachineInfo.of(app.trim(), ip.trim(), port)); | |
137 | + if (allApis.stream().map(o -> o.getApiName()).anyMatch(o -> o.equals(apiName.trim()))) { | |
138 | + return Result.ofFail(-1, "apiName exists: " + apiName); | |
139 | + } | |
140 | + | |
141 | + Date date = new Date(); | |
142 | + entity.setGmtCreate(date); | |
143 | + entity.setGmtModified(date); | |
144 | + | |
145 | + try { | |
146 | + entity = repository.save(entity); | |
147 | + } catch (Throwable throwable) { | |
148 | + logger.error("add gateway api error:", throwable); | |
149 | + return Result.ofThrowable(-1, throwable); | |
150 | + } | |
151 | + | |
152 | + if (!publishApis(app, ip, port)) { | |
153 | + logger.warn("publish gateway apis fail after add"); | |
154 | + } | |
155 | + | |
156 | + return Result.ofSuccess(entity); | |
157 | + } | |
158 | + | |
159 | + @PostMapping("/save.json") | |
160 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
161 | + public Result<ApiDefinitionEntity> updateApi(@RequestBody UpdateApiReqVo reqVo) { | |
162 | + String app = reqVo.getApp(); | |
163 | + if (StringUtil.isBlank(app)) { | |
164 | + return Result.ofFail(-1, "app can't be null or empty"); | |
165 | + } | |
166 | + | |
167 | + Long id = reqVo.getId(); | |
168 | + if (id == null) { | |
169 | + return Result.ofFail(-1, "id can't be null"); | |
170 | + } | |
171 | + | |
172 | + ApiDefinitionEntity entity = repository.findById(id); | |
173 | + if (entity == null) { | |
174 | + return Result.ofFail(-1, "api does not exist, id=" + id); | |
175 | + } | |
176 | + | |
177 | + // 匹配规则列表 | |
178 | + List<ApiPredicateItemVo> predicateItems = reqVo.getPredicateItems(); | |
179 | + if (CollectionUtils.isEmpty(predicateItems)) { | |
180 | + return Result.ofFail(-1, "predicateItems can't empty"); | |
181 | + } | |
182 | + | |
183 | + List<ApiPredicateItemEntity> predicateItemEntities = new ArrayList<>(); | |
184 | + for (ApiPredicateItemVo predicateItem : predicateItems) { | |
185 | + ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity(); | |
186 | + | |
187 | + // 匹配模式 | |
188 | + int matchStrategy = predicateItem.getMatchStrategy(); | |
189 | + if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) { | |
190 | + return Result.ofFail(-1, "Invalid matchStrategy: " + matchStrategy); | |
191 | + } | |
192 | + predicateItemEntity.setMatchStrategy(matchStrategy); | |
193 | + | |
194 | + // 匹配串 | |
195 | + String pattern = predicateItem.getPattern(); | |
196 | + if (StringUtil.isBlank(pattern)) { | |
197 | + return Result.ofFail(-1, "pattern can't be null or empty"); | |
198 | + } | |
199 | + predicateItemEntity.setPattern(pattern); | |
200 | + | |
201 | + predicateItemEntities.add(predicateItemEntity); | |
202 | + } | |
203 | + entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities)); | |
204 | + | |
205 | + Date date = new Date(); | |
206 | + entity.setGmtModified(date); | |
207 | + | |
208 | + try { | |
209 | + entity = repository.save(entity); | |
210 | + } catch (Throwable throwable) { | |
211 | + logger.error("update gateway api error:", throwable); | |
212 | + return Result.ofThrowable(-1, throwable); | |
213 | + } | |
214 | + | |
215 | + if (!publishApis(app, entity.getIp(), entity.getPort())) { | |
216 | + logger.warn("publish gateway apis fail after update"); | |
217 | + } | |
218 | + | |
219 | + return Result.ofSuccess(entity); | |
220 | + } | |
221 | + | |
222 | + @PostMapping("/delete.json") | |
223 | + @AuthAction(AuthService.PrivilegeType.DELETE_RULE) | |
224 | + public Result<Long> deleteApi(Long id) { | |
225 | + if (id == null) { | |
226 | + return Result.ofFail(-1, "id can't be null"); | |
227 | + } | |
228 | + | |
229 | + ApiDefinitionEntity oldEntity = repository.findById(id); | |
230 | + if (oldEntity == null) { | |
231 | + return Result.ofSuccess(null); | |
232 | + } | |
233 | + | |
234 | + try { | |
235 | + repository.delete(id); | |
236 | + } catch (Throwable throwable) { | |
237 | + logger.error("delete gateway api error:", throwable); | |
238 | + return Result.ofThrowable(-1, throwable); | |
239 | + } | |
240 | + | |
241 | + if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) { | |
242 | + logger.warn("publish gateway apis fail after delete"); | |
243 | + } | |
244 | + return Result.ofSuccess(id); | |
245 | + } | |
246 | + | |
247 | + private boolean publishApis(String app, String ip, Integer port) { | |
248 | + List<ApiDefinitionEntity> apis = repository.findAllByApp(app); | |
249 | + try { | |
250 | + apiPublisher.publish(app, apis); | |
251 | + //延迟加载 | |
252 | + delayTime(); | |
253 | + return true; | |
254 | + } catch (Exception e) { | |
255 | + logger.error("publish api error!"); | |
256 | + e.printStackTrace(); | |
257 | + return false; | |
258 | + } | |
259 | + } | |
260 | +} | |
0 | 261 | \ No newline at end of file |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.controller.gateway; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
4 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService; | |
5 | +import com.alibaba.csp.sentinel.dashboard.controller.BaseRuleController; | |
6 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | |
7 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayParamFlowItemEntity; | |
8 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
9 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.AddFlowRuleReqVo; | |
10 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.GatewayParamFlowItemVo; | |
11 | +import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.UpdateFlowRuleReqVo; | |
12 | +import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemGatewayFlowRuleStore; | |
13 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
14 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
15 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
16 | +import org.slf4j.Logger; | |
17 | +import org.slf4j.LoggerFactory; | |
18 | +import org.springframework.beans.factory.annotation.Autowired; | |
19 | +import org.springframework.beans.factory.annotation.Qualifier; | |
20 | +import org.springframework.web.bind.annotation.*; | |
21 | + | |
22 | +import java.util.Arrays; | |
23 | +import java.util.Date; | |
24 | +import java.util.List; | |
25 | + | |
26 | +import static com.alibaba.csp.sentinel.slots.block.RuleConstant.*; | |
27 | +import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*; | |
28 | +import static com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity.*; | |
29 | + | |
30 | +/** | |
31 | + * 网关限流规则控制器 | |
32 | + * | |
33 | + * @author zyf | |
34 | + * @date 2022-04-13 | |
35 | + */ | |
36 | +@RestController | |
37 | +@RequestMapping(value = "/gateway/flow") | |
38 | +public class GatewayFlowRuleController extends BaseRuleController { | |
39 | + | |
40 | + private final Logger logger = LoggerFactory.getLogger(GatewayFlowRuleController.class); | |
41 | + | |
42 | + @Autowired | |
43 | + private InMemGatewayFlowRuleStore repository; | |
44 | + | |
45 | + @Autowired | |
46 | + @Qualifier("gateWayFlowRulesNacosProvider") | |
47 | + private DynamicRuleProvider<List<GatewayFlowRuleEntity>> ruleProvider; | |
48 | + | |
49 | + @Autowired | |
50 | + @Qualifier("gateWayFlowRulesNacosPublisher") | |
51 | + private DynamicRulePublisher<List<GatewayFlowRuleEntity>> rulePublisher; | |
52 | + | |
53 | + @GetMapping("/list.json") | |
54 | + @AuthAction(AuthService.PrivilegeType.READ_RULE) | |
55 | + public Result<List<GatewayFlowRuleEntity>> queryFlowRules(String app, String ip, Integer port) { | |
56 | + | |
57 | + if (StringUtil.isEmpty(app)) { | |
58 | + return Result.ofFail(-1, "app can't be null or empty"); | |
59 | + } | |
60 | + if (StringUtil.isEmpty(ip)) { | |
61 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
62 | + } | |
63 | + if (port == null) { | |
64 | + return Result.ofFail(-1, "port can't be null"); | |
65 | + } | |
66 | + | |
67 | + try { | |
68 | + List<GatewayFlowRuleEntity> rules = ruleProvider.getRules(app); | |
69 | + repository.saveAll(rules); | |
70 | + return Result.ofSuccess(rules); | |
71 | + } catch (Throwable throwable) { | |
72 | + logger.error("query gateway flow rules error:", throwable); | |
73 | + return Result.ofThrowable(-1, throwable); | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + @PostMapping("/new.json") | |
78 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
79 | + public Result<GatewayFlowRuleEntity> addFlowRule(@RequestBody AddFlowRuleReqVo reqVo) { | |
80 | + | |
81 | + String app = reqVo.getApp(); | |
82 | + if (StringUtil.isBlank(app)) { | |
83 | + return Result.ofFail(-1, "app can't be null or empty"); | |
84 | + } | |
85 | + | |
86 | + GatewayFlowRuleEntity entity = new GatewayFlowRuleEntity(); | |
87 | + entity.setApp(app.trim()); | |
88 | + | |
89 | + String ip = reqVo.getIp(); | |
90 | + if (StringUtil.isBlank(ip)) { | |
91 | + return Result.ofFail(-1, "ip can't be null or empty"); | |
92 | + } | |
93 | + entity.setIp(ip.trim()); | |
94 | + | |
95 | + Integer port = reqVo.getPort(); | |
96 | + if (port == null) { | |
97 | + return Result.ofFail(-1, "port can't be null"); | |
98 | + } | |
99 | + entity.setPort(port); | |
100 | + | |
101 | + // API类型, Route ID或API分组 | |
102 | + Integer resourceMode = reqVo.getResourceMode(); | |
103 | + if (resourceMode == null) { | |
104 | + return Result.ofFail(-1, "resourceMode can't be null"); | |
105 | + } | |
106 | + if (!Arrays.asList(RESOURCE_MODE_ROUTE_ID, RESOURCE_MODE_CUSTOM_API_NAME).contains(resourceMode)) { | |
107 | + return Result.ofFail(-1, "invalid resourceMode: " + resourceMode); | |
108 | + } | |
109 | + entity.setResourceMode(resourceMode); | |
110 | + | |
111 | + // API名称 | |
112 | + String resource = reqVo.getResource(); | |
113 | + if (StringUtil.isBlank(resource)) { | |
114 | + return Result.ofFail(-1, "resource can't be null or empty"); | |
115 | + } | |
116 | + entity.setResource(resource.trim()); | |
117 | + | |
118 | + // 针对请求属性 | |
119 | + GatewayParamFlowItemVo paramItem = reqVo.getParamItem(); | |
120 | + if (paramItem != null) { | |
121 | + GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity(); | |
122 | + entity.setParamItem(itemEntity); | |
123 | + | |
124 | + // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie | |
125 | + Integer parseStrategy = paramItem.getParseStrategy(); | |
126 | + if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER | |
127 | + , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) { | |
128 | + return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy); | |
129 | + } | |
130 | + itemEntity.setParseStrategy(paramItem.getParseStrategy()); | |
131 | + | |
132 | + // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填 | |
133 | + if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) { | |
134 | + // 参数名称 | |
135 | + String fieldName = paramItem.getFieldName(); | |
136 | + if (StringUtil.isBlank(fieldName)) { | |
137 | + return Result.ofFail(-1, "fieldName can't be null or empty"); | |
138 | + } | |
139 | + itemEntity.setFieldName(paramItem.getFieldName()); | |
140 | + } | |
141 | + | |
142 | + String pattern = paramItem.getPattern(); | |
143 | + // 如果匹配串不为空,验证匹配模式 | |
144 | + if (StringUtil.isNotEmpty(pattern)) { | |
145 | + itemEntity.setPattern(pattern); | |
146 | + Integer matchStrategy = paramItem.getMatchStrategy(); | |
147 | + if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) { | |
148 | + return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy); | |
149 | + } | |
150 | + itemEntity.setMatchStrategy(matchStrategy); | |
151 | + } | |
152 | + } | |
153 | + | |
154 | + // 阈值类型 0-线程数 1-QPS | |
155 | + Integer grade = reqVo.getGrade(); | |
156 | + if (grade == null) { | |
157 | + return Result.ofFail(-1, "grade can't be null"); | |
158 | + } | |
159 | + if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) { | |
160 | + return Result.ofFail(-1, "invalid grade: " + grade); | |
161 | + } | |
162 | + entity.setGrade(grade); | |
163 | + | |
164 | + // QPS阈值 | |
165 | + Double count = reqVo.getCount(); | |
166 | + if (count == null) { | |
167 | + return Result.ofFail(-1, "count can't be null"); | |
168 | + } | |
169 | + if (count < 0) { | |
170 | + return Result.ofFail(-1, "count should be at lease zero"); | |
171 | + } | |
172 | + entity.setCount(count); | |
173 | + | |
174 | + // 间隔 | |
175 | + Long interval = reqVo.getInterval(); | |
176 | + if (interval == null) { | |
177 | + return Result.ofFail(-1, "interval can't be null"); | |
178 | + } | |
179 | + if (interval <= 0) { | |
180 | + return Result.ofFail(-1, "interval should be greater than zero"); | |
181 | + } | |
182 | + entity.setInterval(interval); | |
183 | + | |
184 | + // 间隔单位 | |
185 | + Integer intervalUnit = reqVo.getIntervalUnit(); | |
186 | + if (intervalUnit == null) { | |
187 | + return Result.ofFail(-1, "intervalUnit can't be null"); | |
188 | + } | |
189 | + if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) { | |
190 | + return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit); | |
191 | + } | |
192 | + entity.setIntervalUnit(intervalUnit); | |
193 | + | |
194 | + // 流控方式 0-快速失败 2-匀速排队 | |
195 | + Integer controlBehavior = reqVo.getControlBehavior(); | |
196 | + if (controlBehavior == null) { | |
197 | + return Result.ofFail(-1, "controlBehavior can't be null"); | |
198 | + } | |
199 | + if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) { | |
200 | + return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior); | |
201 | + } | |
202 | + entity.setControlBehavior(controlBehavior); | |
203 | + | |
204 | + if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) { | |
205 | + // 0-快速失败, 则Burst size必填 | |
206 | + Integer burst = reqVo.getBurst(); | |
207 | + if (burst == null) { | |
208 | + return Result.ofFail(-1, "burst can't be null"); | |
209 | + } | |
210 | + if (burst < 0) { | |
211 | + return Result.ofFail(-1, "invalid burst: " + burst); | |
212 | + } | |
213 | + entity.setBurst(burst); | |
214 | + } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) { | |
215 | + // 1-匀速排队, 则超时时间必填 | |
216 | + Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs(); | |
217 | + if (maxQueueingTimeoutMs == null) { | |
218 | + return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null"); | |
219 | + } | |
220 | + if (maxQueueingTimeoutMs < 0) { | |
221 | + return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs); | |
222 | + } | |
223 | + entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs); | |
224 | + } | |
225 | + | |
226 | + Date date = new Date(); | |
227 | + entity.setGmtCreate(date); | |
228 | + entity.setGmtModified(date); | |
229 | + | |
230 | + try { | |
231 | + entity = repository.save(entity); | |
232 | + } catch (Throwable throwable) { | |
233 | + logger.error("add gateway flow rule error:", throwable); | |
234 | + return Result.ofThrowable(-1, throwable); | |
235 | + } | |
236 | + | |
237 | + if (!publishRules(app, ip, port)) { | |
238 | + logger.warn("publish gateway flow rules fail after add"); | |
239 | + } | |
240 | + | |
241 | + return Result.ofSuccess(entity); | |
242 | + } | |
243 | + | |
244 | + @PostMapping("/save.json") | |
245 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
246 | + public Result<GatewayFlowRuleEntity> updateFlowRule(@RequestBody UpdateFlowRuleReqVo reqVo) { | |
247 | + | |
248 | + String app = reqVo.getApp(); | |
249 | + if (StringUtil.isBlank(app)) { | |
250 | + return Result.ofFail(-1, "app can't be null or empty"); | |
251 | + } | |
252 | + | |
253 | + Long id = reqVo.getId(); | |
254 | + if (id == null) { | |
255 | + return Result.ofFail(-1, "id can't be null"); | |
256 | + } | |
257 | + | |
258 | + GatewayFlowRuleEntity entity = repository.findById(id); | |
259 | + if (entity == null) { | |
260 | + return Result.ofFail(-1, "gateway flow rule does not exist, id=" + id); | |
261 | + } | |
262 | + | |
263 | + // 针对请求属性 | |
264 | + GatewayParamFlowItemVo paramItem = reqVo.getParamItem(); | |
265 | + if (paramItem != null) { | |
266 | + GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity(); | |
267 | + entity.setParamItem(itemEntity); | |
268 | + | |
269 | + // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie | |
270 | + Integer parseStrategy = paramItem.getParseStrategy(); | |
271 | + if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER | |
272 | + , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) { | |
273 | + return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy); | |
274 | + } | |
275 | + itemEntity.setParseStrategy(paramItem.getParseStrategy()); | |
276 | + | |
277 | + // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填 | |
278 | + if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) { | |
279 | + // 参数名称 | |
280 | + String fieldName = paramItem.getFieldName(); | |
281 | + if (StringUtil.isBlank(fieldName)) { | |
282 | + return Result.ofFail(-1, "fieldName can't be null or empty"); | |
283 | + } | |
284 | + itemEntity.setFieldName(paramItem.getFieldName()); | |
285 | + } | |
286 | + | |
287 | + String pattern = paramItem.getPattern(); | |
288 | + // 如果匹配串不为空,验证匹配模式 | |
289 | + if (StringUtil.isNotEmpty(pattern)) { | |
290 | + itemEntity.setPattern(pattern); | |
291 | + Integer matchStrategy = paramItem.getMatchStrategy(); | |
292 | + if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) { | |
293 | + return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy); | |
294 | + } | |
295 | + itemEntity.setMatchStrategy(matchStrategy); | |
296 | + } | |
297 | + } else { | |
298 | + entity.setParamItem(null); | |
299 | + } | |
300 | + | |
301 | + // 阈值类型 0-线程数 1-QPS | |
302 | + Integer grade = reqVo.getGrade(); | |
303 | + if (grade == null) { | |
304 | + return Result.ofFail(-1, "grade can't be null"); | |
305 | + } | |
306 | + if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) { | |
307 | + return Result.ofFail(-1, "invalid grade: " + grade); | |
308 | + } | |
309 | + entity.setGrade(grade); | |
310 | + | |
311 | + // QPS阈值 | |
312 | + Double count = reqVo.getCount(); | |
313 | + if (count == null) { | |
314 | + return Result.ofFail(-1, "count can't be null"); | |
315 | + } | |
316 | + if (count < 0) { | |
317 | + return Result.ofFail(-1, "count should be at lease zero"); | |
318 | + } | |
319 | + entity.setCount(count); | |
320 | + | |
321 | + // 间隔 | |
322 | + Long interval = reqVo.getInterval(); | |
323 | + if (interval == null) { | |
324 | + return Result.ofFail(-1, "interval can't be null"); | |
325 | + } | |
326 | + if (interval <= 0) { | |
327 | + return Result.ofFail(-1, "interval should be greater than zero"); | |
328 | + } | |
329 | + entity.setInterval(interval); | |
330 | + | |
331 | + // 间隔单位 | |
332 | + Integer intervalUnit = reqVo.getIntervalUnit(); | |
333 | + if (intervalUnit == null) { | |
334 | + return Result.ofFail(-1, "intervalUnit can't be null"); | |
335 | + } | |
336 | + if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) { | |
337 | + return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit); | |
338 | + } | |
339 | + entity.setIntervalUnit(intervalUnit); | |
340 | + | |
341 | + // 流控方式 0-快速失败 2-匀速排队 | |
342 | + Integer controlBehavior = reqVo.getControlBehavior(); | |
343 | + if (controlBehavior == null) { | |
344 | + return Result.ofFail(-1, "controlBehavior can't be null"); | |
345 | + } | |
346 | + if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) { | |
347 | + return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior); | |
348 | + } | |
349 | + entity.setControlBehavior(controlBehavior); | |
350 | + | |
351 | + if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) { | |
352 | + // 0-快速失败, 则Burst size必填 | |
353 | + Integer burst = reqVo.getBurst(); | |
354 | + if (burst == null) { | |
355 | + return Result.ofFail(-1, "burst can't be null"); | |
356 | + } | |
357 | + if (burst < 0) { | |
358 | + return Result.ofFail(-1, "invalid burst: " + burst); | |
359 | + } | |
360 | + entity.setBurst(burst); | |
361 | + } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) { | |
362 | + // 2-匀速排队, 则超时时间必填 | |
363 | + Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs(); | |
364 | + if (maxQueueingTimeoutMs == null) { | |
365 | + return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null"); | |
366 | + } | |
367 | + if (maxQueueingTimeoutMs < 0) { | |
368 | + return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs); | |
369 | + } | |
370 | + entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs); | |
371 | + } | |
372 | + | |
373 | + Date date = new Date(); | |
374 | + entity.setGmtModified(date); | |
375 | + | |
376 | + try { | |
377 | + entity = repository.save(entity); | |
378 | + } catch (Throwable throwable) { | |
379 | + logger.error("update gateway flow rule error:", throwable); | |
380 | + return Result.ofThrowable(-1, throwable); | |
381 | + } | |
382 | + | |
383 | + if (!publishRules(app, entity.getIp(), entity.getPort())) { | |
384 | + logger.warn("publish gateway flow rules fail after update"); | |
385 | + } | |
386 | + | |
387 | + return Result.ofSuccess(entity); | |
388 | + } | |
389 | + | |
390 | + | |
391 | + @PostMapping("/delete.json") | |
392 | + @AuthAction(AuthService.PrivilegeType.DELETE_RULE) | |
393 | + public Result<Long> deleteFlowRule(Long id) { | |
394 | + | |
395 | + if (id == null) { | |
396 | + return Result.ofFail(-1, "id can't be null"); | |
397 | + } | |
398 | + | |
399 | + GatewayFlowRuleEntity oldEntity = repository.findById(id); | |
400 | + if (oldEntity == null) { | |
401 | + return Result.ofSuccess(null); | |
402 | + } | |
403 | + | |
404 | + try { | |
405 | + repository.delete(id); | |
406 | + } catch (Throwable throwable) { | |
407 | + logger.error("delete gateway flow rule error:", throwable); | |
408 | + return Result.ofThrowable(-1, throwable); | |
409 | + } | |
410 | + | |
411 | + if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) { | |
412 | + logger.warn("publish gateway flow rules fail after delete"); | |
413 | + } | |
414 | + | |
415 | + return Result.ofSuccess(id); | |
416 | + } | |
417 | + | |
418 | + private boolean publishRules(String app, String ip, Integer port) { | |
419 | + List<GatewayFlowRuleEntity> rules = repository.findAllByApp(app); | |
420 | + try { | |
421 | + rulePublisher.publish(app, rules); | |
422 | + //延迟加载 | |
423 | + delayTime(); | |
424 | + return true; | |
425 | + } catch (Exception e) { | |
426 | + logger.error("publish rules error!"); | |
427 | + e.printStackTrace(); | |
428 | + return false; | |
429 | + } | |
430 | + } | |
431 | +} | |
0 | 432 | \ No newline at end of file |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java
0 → 100644
1 | +/* | |
2 | + * Copyright 1999-2018 Alibaba Group Holding Ltd. | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package com.alibaba.csp.sentinel.dashboard.controller.v2; | |
17 | + | |
18 | +import java.util.Date; | |
19 | +import java.util.List; | |
20 | + | |
21 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; | |
22 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService; | |
23 | +import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; | |
24 | +import com.alibaba.csp.sentinel.dashboard.controller.BaseRuleController; | |
25 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
26 | + | |
27 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | |
28 | +import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter; | |
29 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
30 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
31 | +import com.alibaba.csp.sentinel.dashboard.domain.Result; | |
32 | + | |
33 | +import org.slf4j.Logger; | |
34 | +import org.slf4j.LoggerFactory; | |
35 | +import org.springframework.beans.factory.annotation.Autowired; | |
36 | +import org.springframework.beans.factory.annotation.Qualifier; | |
37 | +import org.springframework.util.ObjectUtils; | |
38 | +import org.springframework.web.bind.annotation.DeleteMapping; | |
39 | +import org.springframework.web.bind.annotation.GetMapping; | |
40 | +import org.springframework.web.bind.annotation.PathVariable; | |
41 | +import org.springframework.web.bind.annotation.PostMapping; | |
42 | +import org.springframework.web.bind.annotation.PutMapping; | |
43 | +import org.springframework.web.bind.annotation.RequestBody; | |
44 | +import org.springframework.web.bind.annotation.RequestMapping; | |
45 | +import org.springframework.web.bind.annotation.RequestParam; | |
46 | +import org.springframework.web.bind.annotation.RestController; | |
47 | + | |
48 | +/** | |
49 | + * 流控规则控制器 | |
50 | + * | |
51 | + * @author zyf | |
52 | + * @date 2022-04-13 | |
53 | + */ | |
54 | +@RestController | |
55 | +@RequestMapping(value = "/v2/flow") | |
56 | +public class FlowControllerV2 extends BaseRuleController { | |
57 | + | |
58 | + private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class); | |
59 | + | |
60 | + @Autowired | |
61 | + private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository; | |
62 | + | |
63 | + @Autowired | |
64 | + @Qualifier("flowRuleNacosProvider") | |
65 | + private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; | |
66 | + @Autowired | |
67 | + @Qualifier("flowRuleNacosPublisher") | |
68 | + private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; | |
69 | + | |
70 | + @GetMapping("/rules") | |
71 | + @AuthAction(PrivilegeType.READ_RULE) | |
72 | + public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) { | |
73 | + | |
74 | + if (StringUtil.isEmpty(app)) { | |
75 | + return Result.ofFail(-1, "app can't be null or empty"); | |
76 | + } | |
77 | + try { | |
78 | + List<FlowRuleEntity> rules = ruleProvider.getRules(app); | |
79 | + if (rules != null && !rules.isEmpty()) { | |
80 | + for (FlowRuleEntity entity : rules) { | |
81 | + entity.setApp(app); | |
82 | + if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) { | |
83 | + entity.setId(entity.getClusterConfig().getFlowId()); | |
84 | + } | |
85 | + } | |
86 | + } | |
87 | + rules = repository.saveAll(rules); | |
88 | + return Result.ofSuccess(rules); | |
89 | + } catch (Throwable throwable) { | |
90 | + logger.error("Error when querying flow rules", throwable); | |
91 | + return Result.ofThrowable(-1, throwable); | |
92 | + } | |
93 | + } | |
94 | + | |
95 | + private <R> Result<R> checkEntityInternal(FlowRuleEntity entity) { | |
96 | + if (entity == null) { | |
97 | + return Result.ofFail(-1, "invalid body"); | |
98 | + } | |
99 | + if (StringUtil.isBlank(entity.getApp())) { | |
100 | + return Result.ofFail(-1, "app can't be null or empty"); | |
101 | + } | |
102 | + if (StringUtil.isBlank(entity.getLimitApp())) { | |
103 | + return Result.ofFail(-1, "limitApp can't be null or empty"); | |
104 | + } | |
105 | + if (StringUtil.isBlank(entity.getResource())) { | |
106 | + return Result.ofFail(-1, "resource can't be null or empty"); | |
107 | + } | |
108 | + if (entity.getGrade() == null) { | |
109 | + return Result.ofFail(-1, "grade can't be null"); | |
110 | + } | |
111 | + if (entity.getGrade() != 0 && entity.getGrade() != 1) { | |
112 | + return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got"); | |
113 | + } | |
114 | + if (entity.getCount() == null || entity.getCount() < 0) { | |
115 | + return Result.ofFail(-1, "count should be at lease zero"); | |
116 | + } | |
117 | + if (entity.getStrategy() == null) { | |
118 | + return Result.ofFail(-1, "strategy can't be null"); | |
119 | + } | |
120 | + if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) { | |
121 | + return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0"); | |
122 | + } | |
123 | + if (entity.getControlBehavior() == null) { | |
124 | + return Result.ofFail(-1, "controlBehavior can't be null"); | |
125 | + } | |
126 | + int controlBehavior = entity.getControlBehavior(); | |
127 | + if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) { | |
128 | + return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1"); | |
129 | + } | |
130 | + if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) { | |
131 | + return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2"); | |
132 | + } | |
133 | + if (entity.isClusterMode() && entity.getClusterConfig() == null) { | |
134 | + return Result.ofFail(-1, "cluster config should be valid"); | |
135 | + } | |
136 | + return null; | |
137 | + } | |
138 | + | |
139 | + @PostMapping("/rule") | |
140 | + @AuthAction(value = AuthService.PrivilegeType.WRITE_RULE) | |
141 | + public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) { | |
142 | + | |
143 | + Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | |
144 | + if (checkResult != null) { | |
145 | + return checkResult; | |
146 | + } | |
147 | + entity.setId(null); | |
148 | + Date date = new Date(); | |
149 | + entity.setGmtCreate(date); | |
150 | + entity.setGmtModified(date); | |
151 | + entity.setLimitApp(entity.getLimitApp().trim()); | |
152 | + entity.setResource(entity.getResource().trim()); | |
153 | + try { | |
154 | + entity = repository.save(entity); | |
155 | + publishRules(entity.getApp()); | |
156 | + } catch (Throwable throwable) { | |
157 | + logger.error("Failed to add flow rule", throwable); | |
158 | + return Result.ofThrowable(-1, throwable); | |
159 | + } | |
160 | + return Result.ofSuccess(entity); | |
161 | + } | |
162 | + | |
163 | + @PutMapping("/rule/{id}") | |
164 | + @AuthAction(AuthService.PrivilegeType.WRITE_RULE) | |
165 | + | |
166 | + public Result<FlowRuleEntity> apiUpdateFlowRule(@PathVariable("id") Long id, | |
167 | + @RequestBody FlowRuleEntity entity) { | |
168 | + if (id == null || id <= 0) { | |
169 | + return Result.ofFail(-1, "Invalid id"); | |
170 | + } | |
171 | + FlowRuleEntity oldEntity = repository.findById(id); | |
172 | + if (oldEntity == null) { | |
173 | + return Result.ofFail(-1, "id " + id + " does not exist"); | |
174 | + } | |
175 | + if (entity == null) { | |
176 | + return Result.ofFail(-1, "invalid body"); | |
177 | + } | |
178 | + | |
179 | + entity.setApp(oldEntity.getApp()); | |
180 | + entity.setIp(oldEntity.getIp()); | |
181 | + entity.setPort(oldEntity.getPort()); | |
182 | + Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | |
183 | + if (checkResult != null) { | |
184 | + return checkResult; | |
185 | + } | |
186 | + | |
187 | + entity.setId(id); | |
188 | + Date date = new Date(); | |
189 | + entity.setGmtCreate(oldEntity.getGmtCreate()); | |
190 | + entity.setGmtModified(date); | |
191 | + try { | |
192 | + entity = repository.save(entity); | |
193 | + if (entity == null) { | |
194 | + return Result.ofFail(-1, "save entity fail"); | |
195 | + } | |
196 | + publishRules(oldEntity.getApp()); | |
197 | + } catch (Throwable throwable) { | |
198 | + logger.error("Failed to update flow rule", throwable); | |
199 | + return Result.ofThrowable(-1, throwable); | |
200 | + } | |
201 | + return Result.ofSuccess(entity); | |
202 | + } | |
203 | + | |
204 | + @DeleteMapping("/rule/{id}") | |
205 | + @AuthAction(PrivilegeType.DELETE_RULE) | |
206 | + public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |
207 | + if (id == null || id <= 0) { | |
208 | + return Result.ofFail(-1, "Invalid id"); | |
209 | + } | |
210 | + FlowRuleEntity oldEntity = repository.findById(id); | |
211 | + if (ObjectUtils.isEmpty(oldEntity)) { | |
212 | + return Result.ofSuccess(null); | |
213 | + } | |
214 | + | |
215 | + try { | |
216 | + repository.delete(id); | |
217 | + publishRules(oldEntity.getApp()); | |
218 | + } catch (Exception e) { | |
219 | + return Result.ofFail(-1, e.getMessage()); | |
220 | + } | |
221 | + return Result.ofSuccess(id); | |
222 | + } | |
223 | + | |
224 | + private void publishRules(/*@NonNull*/ String app) throws Exception { | |
225 | + List<FlowRuleEntity> rules = repository.findAllByApp(app); | |
226 | + rulePublisher.publish(app, rules); | |
227 | + //延迟加载 | |
228 | + delayTime(); | |
229 | + } | |
230 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/NacosConfigProperties.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos; | |
2 | + | |
3 | +/** | |
4 | + * @Description: nacos配置 | |
5 | + * @author: zyf | |
6 | + * @date: 2022/03/01$ | |
7 | + * @version: V1.0 | |
8 | + */ | |
9 | +import lombok.Data; | |
10 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
11 | +import org.springframework.stereotype.Component; | |
12 | + | |
13 | +@Component | |
14 | +@ConfigurationProperties(prefix = "nacos.server") | |
15 | +@Data | |
16 | +public class NacosConfigProperties { | |
17 | + | |
18 | + private String ip; | |
19 | + | |
20 | + private String namespace; | |
21 | + | |
22 | + private String username; | |
23 | + | |
24 | + private String password; | |
25 | + | |
26 | + private String groupId; | |
27 | + | |
28 | + public String getServerAddr() { | |
29 | + return this.getIp(); | |
30 | + } | |
31 | + | |
32 | +} | |
0 | 33 | \ No newline at end of file |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/SentinelConfig.java
0 → 100644
1 | +/* | |
2 | + * Copyright 1999-2018 Alibaba Group Holding Ltd. | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos; | |
17 | + | |
18 | +import java.util.List; | |
19 | +import java.util.Properties; | |
20 | + | |
21 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | |
22 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | |
23 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.*; | |
24 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.AuthorityRuleCorrectEntity; | |
25 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.ParamFlowRuleCorrectEntity; | |
26 | +import com.alibaba.nacos.api.PropertyKeyConst; | |
27 | +import org.springframework.beans.factory.annotation.Autowired; | |
28 | +import org.springframework.context.annotation.Bean; | |
29 | +import org.springframework.context.annotation.Configuration; | |
30 | + | |
31 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
32 | +import com.alibaba.fastjson.JSON; | |
33 | +import com.alibaba.nacos.api.config.ConfigFactory; | |
34 | +import com.alibaba.nacos.api.config.ConfigService; | |
35 | + | |
36 | +/** | |
37 | + * sentinel配置类 | |
38 | + * | |
39 | + * @author zyf | |
40 | + * @date 2022-04-13 | |
41 | + */ | |
42 | +@Configuration | |
43 | +public class SentinelConfig { | |
44 | + | |
45 | + @Autowired | |
46 | + private NacosConfigProperties nacosConfigProperties; | |
47 | + | |
48 | + | |
49 | + /** | |
50 | + * 流控规则 | |
51 | + * @return | |
52 | + */ | |
53 | + @Bean | |
54 | + public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() { | |
55 | + return JSON::toJSONString; | |
56 | + } | |
57 | + | |
58 | + @Bean | |
59 | + public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() { | |
60 | + return s -> JSON.parseArray(s, FlowRuleEntity.class); | |
61 | + } | |
62 | + /** | |
63 | + * 降级规则 | |
64 | + * @return | |
65 | + */ | |
66 | + @Bean | |
67 | + public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() { | |
68 | + return JSON::toJSONString; | |
69 | + } | |
70 | + | |
71 | + @Bean | |
72 | + public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() { | |
73 | + return s -> JSON.parseArray(s, DegradeRuleEntity.class); | |
74 | + } | |
75 | + | |
76 | + /** | |
77 | + * 热点参数 规则 | |
78 | + * @return | |
79 | + */ | |
80 | + @Bean | |
81 | + public Converter<List<ParamFlowRuleCorrectEntity>, String> paramFlowRuleEntityEncoder() { | |
82 | + return JSON::toJSONString; | |
83 | + } | |
84 | + | |
85 | + @Bean | |
86 | + public Converter<String, List<ParamFlowRuleCorrectEntity>> paramFlowRuleEntityDecoder() { | |
87 | + return s -> JSON.parseArray(s, ParamFlowRuleCorrectEntity.class); | |
88 | + } | |
89 | + | |
90 | + /** | |
91 | + * 系统规则 | |
92 | + * @return | |
93 | + */ | |
94 | + @Bean | |
95 | + public Converter<List<SystemRuleEntity>, String> systemRuleRuleEntityEncoder() { | |
96 | + return JSON::toJSONString; | |
97 | + } | |
98 | + | |
99 | + @Bean | |
100 | + public Converter<String, List<SystemRuleEntity>> systemRuleRuleEntityDecoder() { | |
101 | + return s -> JSON.parseArray(s, SystemRuleEntity.class); | |
102 | + } | |
103 | + /** | |
104 | + * 授权规则 | |
105 | + * @return | |
106 | + */ | |
107 | + @Bean | |
108 | + public Converter<List<AuthorityRuleCorrectEntity>, String> authorityRuleRuleEntityEncoder() { | |
109 | + return JSON::toJSONString; | |
110 | + } | |
111 | + | |
112 | + @Bean | |
113 | + public Converter<String, List<AuthorityRuleCorrectEntity>> authorityRuleRuleEntityDecoder() { | |
114 | + return s -> JSON.parseArray(s, AuthorityRuleCorrectEntity.class); | |
115 | + } | |
116 | + | |
117 | + /** | |
118 | + * 网关API | |
119 | + * | |
120 | + * @return | |
121 | + * @throws Exception | |
122 | + */ | |
123 | + @Bean | |
124 | + public Converter<List<ApiDefinitionEntity>, String> apiDefinitionEntityEncoder() { | |
125 | + return JSON::toJSONString; | |
126 | + } | |
127 | + | |
128 | + @Bean | |
129 | + public Converter<String, List<ApiDefinitionEntity>> apiDefinitionEntityDecoder() { | |
130 | + return s -> JSON.parseArray(s, ApiDefinitionEntity.class); | |
131 | + } | |
132 | + | |
133 | + /** | |
134 | + * 网关flowRule | |
135 | + * | |
136 | + * @return | |
137 | + * @throws Exception | |
138 | + */ | |
139 | + @Bean | |
140 | + public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() { | |
141 | + return JSON::toJSONString; | |
142 | + } | |
143 | + | |
144 | + @Bean | |
145 | + public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() { | |
146 | + return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class); | |
147 | + } | |
148 | + | |
149 | + @Bean | |
150 | + public ConfigService nacosConfigService() throws Exception { | |
151 | + Properties properties=new Properties(); | |
152 | + properties.put(PropertyKeyConst.SERVER_ADDR,nacosConfigProperties.getServerAddr()); | |
153 | + properties.put(PropertyKeyConst.USERNAME,nacosConfigProperties.getUsername()); | |
154 | + properties.put(PropertyKeyConst.PASSWORD,nacosConfigProperties.getPassword()); | |
155 | + return ConfigFactory.createConfigService(properties); | |
156 | + } | |
157 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/authority/AuthorityRuleNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.authority; | |
2 | + | |
3 | + | |
4 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
5 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
7 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.AuthorityRuleCorrectEntity; | |
8 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
9 | +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; | |
10 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
11 | +import com.alibaba.nacos.api.config.ConfigService; | |
12 | +import org.springframework.beans.BeanUtils; | |
13 | +import org.springframework.beans.factory.annotation.Autowired; | |
14 | +import org.springframework.stereotype.Component; | |
15 | + | |
16 | +import java.util.ArrayList; | |
17 | +import java.util.List; | |
18 | +import java.util.stream.Collectors; | |
19 | + | |
20 | +/** | |
21 | + * 授权规则拉取(黑名单白名单) | |
22 | + * | |
23 | + * @author zyf | |
24 | + * @date 2022-04-13 | |
25 | + */ | |
26 | +@Component("authorityRuleNacosProvider") | |
27 | +public class AuthorityRuleNacosProvider implements DynamicRuleProvider<List<AuthorityRuleEntity>> { | |
28 | + @Autowired | |
29 | + private ConfigService configService; | |
30 | + @Autowired | |
31 | + private Converter<String, List<AuthorityRuleCorrectEntity>> converter; | |
32 | + | |
33 | + @Override | |
34 | + public List<AuthorityRuleEntity> getRules(String appName) throws Exception { | |
35 | + String rules = configService.getConfig(appName + SentinelConStants.AUTHORITY_DATA_ID_POSTFIX, | |
36 | + SentinelConStants.GROUP_ID, 3000); | |
37 | + if (StringUtil.isEmpty(rules)) { | |
38 | + return new ArrayList<>(); | |
39 | + } | |
40 | + List<AuthorityRuleCorrectEntity> entityList = converter.convert(rules); | |
41 | + return entityList.stream().map(rule -> { | |
42 | + AuthorityRule authorityRule = new AuthorityRule(); | |
43 | + BeanUtils.copyProperties(rule, authorityRule); | |
44 | + AuthorityRuleEntity entity = AuthorityRuleEntity.fromAuthorityRule(rule.getApp(), rule.getIp(), rule.getPort(), authorityRule); | |
45 | + entity.setId(rule.getId()); | |
46 | + entity.setGmtCreate(rule.getGmtCreate()); | |
47 | + return entity; | |
48 | + }).collect(Collectors.toList()); | |
49 | + } | |
50 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/authority/AuthorityRuleNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.authority; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.AuthorityRuleCorrectEntity; | |
7 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
8 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
9 | +import com.alibaba.nacos.api.config.ConfigService; | |
10 | +import org.springframework.beans.BeanUtils; | |
11 | +import org.springframework.beans.factory.annotation.Autowired; | |
12 | +import org.springframework.stereotype.Component; | |
13 | + | |
14 | +import java.util.List; | |
15 | +import java.util.stream.Collectors; | |
16 | + | |
17 | +/** | |
18 | + * 授权规则持久化(黑名单白名单) | |
19 | + * | |
20 | + * @author zyf | |
21 | + * @date 2022-04-13 | |
22 | + */ | |
23 | +@Component("authorityRuleNacosPublisher") | |
24 | +public class AuthorityRuleNacosPublisher implements DynamicRulePublisher<List<AuthorityRuleEntity>> { | |
25 | + @Autowired | |
26 | + private ConfigService configService; | |
27 | + @Autowired | |
28 | + private Converter<List<AuthorityRuleCorrectEntity>, String> converter; | |
29 | + | |
30 | + @Override | |
31 | + public void publish(String app, List<AuthorityRuleEntity> rules) throws Exception { | |
32 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
33 | + if (rules == null) { | |
34 | + return; | |
35 | + } | |
36 | + // 转换 | |
37 | + List<AuthorityRuleCorrectEntity> list = rules.stream().map(rule -> { | |
38 | + AuthorityRuleCorrectEntity entity = new AuthorityRuleCorrectEntity(); | |
39 | + BeanUtils.copyProperties(rule, entity); | |
40 | + return entity; | |
41 | + }).collect(Collectors.toList()); | |
42 | + | |
43 | + configService.publishConfig(app + SentinelConStants.AUTHORITY_DATA_ID_POSTFIX, | |
44 | + SentinelConStants.GROUP_ID, converter.convert(list)); | |
45 | + } | |
46 | +} | |
47 | + | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/degrade/DegradeRuleNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
7 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
8 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
9 | +import com.alibaba.nacos.api.config.ConfigService; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.springframework.stereotype.Component; | |
12 | + | |
13 | +import java.util.ArrayList; | |
14 | +import java.util.List; | |
15 | + | |
16 | +/** | |
17 | + * 降级规则拉取 | |
18 | + * | |
19 | + * @author zyf | |
20 | + * @date 2022-04-13 | |
21 | + */ | |
22 | +@Component("degradeRuleNacosProvider") | |
23 | +public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> { | |
24 | + | |
25 | + @Autowired | |
26 | + private ConfigService configService; | |
27 | + @Autowired | |
28 | + private Converter<String, List<DegradeRuleEntity>> converter; | |
29 | + | |
30 | + @Override | |
31 | + public List<DegradeRuleEntity> getRules(String appName) throws Exception { | |
32 | + String rules = configService.getConfig(appName + SentinelConStants.DEGRADE_DATA_ID_POSTFIX, | |
33 | + SentinelConStants.GROUP_ID, 3000); | |
34 | + if (StringUtil.isEmpty(rules)) { | |
35 | + return new ArrayList<>(); | |
36 | + } | |
37 | + return converter.convert(rules); | |
38 | + } | |
39 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/degrade/DegradeRuleNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
7 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
8 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
9 | +import com.alibaba.nacos.api.config.ConfigService; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.springframework.stereotype.Component; | |
12 | + | |
13 | +import java.util.List; | |
14 | + | |
15 | +/** | |
16 | + * 降级规则推送 | |
17 | + * | |
18 | + * @author zyf | |
19 | + * @date 2022-04-13 | |
20 | + */ | |
21 | +@Component("degradeRuleNacosPublisher") | |
22 | +public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> { | |
23 | + | |
24 | + @Autowired | |
25 | + private ConfigService configService; | |
26 | + @Autowired | |
27 | + private Converter<List<DegradeRuleEntity>, String> converter; | |
28 | + | |
29 | + @Override | |
30 | + public void publish(String app, List<DegradeRuleEntity> rules) throws Exception { | |
31 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
32 | + if (rules == null) { | |
33 | + return; | |
34 | + } | |
35 | + configService.publishConfig(app + SentinelConStants.DEGRADE_DATA_ID_POSTFIX, | |
36 | + SentinelConStants.GROUP_ID, converter.convert(rules)); | |
37 | + } | |
38 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/entity/AuthorityRuleCorrectEntity.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.entity; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity; | |
4 | +import com.alibaba.csp.sentinel.slots.block.Rule; | |
5 | +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; | |
6 | + | |
7 | +import java.util.Date; | |
8 | + | |
9 | +/** | |
10 | + * @author zyf | |
11 | + * @description 重写授权规则实体类,原因同热点规则 | |
12 | + * @date 2022-04-13 | |
13 | + */ | |
14 | +public class AuthorityRuleCorrectEntity implements RuleEntity { | |
15 | + | |
16 | + private Long id; | |
17 | + private String app; | |
18 | + private String ip; | |
19 | + private Integer port; | |
20 | + private String limitApp; | |
21 | + private String resource; | |
22 | + private Date gmtCreate; | |
23 | + private Date gmtModified; | |
24 | + | |
25 | + private int strategy; | |
26 | + | |
27 | + @Override | |
28 | + public Long getId() { | |
29 | + return id; | |
30 | + } | |
31 | + | |
32 | + @Override | |
33 | + public void setId(Long id) { | |
34 | + this.id = id; | |
35 | + } | |
36 | + | |
37 | + @Override | |
38 | + public String getApp() { | |
39 | + return app; | |
40 | + } | |
41 | + | |
42 | + public void setApp(String app) { | |
43 | + this.app = app; | |
44 | + } | |
45 | + | |
46 | + @Override | |
47 | + public String getIp() { | |
48 | + return ip; | |
49 | + } | |
50 | + | |
51 | + public void setIp(String ip) { | |
52 | + this.ip = ip; | |
53 | + } | |
54 | + | |
55 | + @Override | |
56 | + public Integer getPort() { | |
57 | + return port; | |
58 | + } | |
59 | + | |
60 | + public void setPort(Integer port) { | |
61 | + this.port = port; | |
62 | + } | |
63 | + | |
64 | + public String getLimitApp() { | |
65 | + return limitApp; | |
66 | + } | |
67 | + | |
68 | + public void setLimitApp(String limitApp) { | |
69 | + this.limitApp = limitApp; | |
70 | + } | |
71 | + | |
72 | + public String getResource() { | |
73 | + return resource; | |
74 | + } | |
75 | + | |
76 | + public void setResource(String resource) { | |
77 | + this.resource = resource; | |
78 | + } | |
79 | + | |
80 | + @Override | |
81 | + public Date getGmtCreate() { | |
82 | + return gmtCreate; | |
83 | + } | |
84 | + | |
85 | + public void setGmtCreate(Date gmtCreate) { | |
86 | + this.gmtCreate = gmtCreate; | |
87 | + } | |
88 | + | |
89 | + public Date getGmtModified() { | |
90 | + return gmtModified; | |
91 | + } | |
92 | + | |
93 | + public void setGmtModified(Date gmtModified) { | |
94 | + this.gmtModified = gmtModified; | |
95 | + } | |
96 | + | |
97 | + public int getStrategy() { | |
98 | + return strategy; | |
99 | + } | |
100 | + | |
101 | + public void setStrategy(int strategy) { | |
102 | + this.strategy = strategy; | |
103 | + } | |
104 | + | |
105 | + @Override | |
106 | + public Rule toRule(){ | |
107 | + AuthorityRule rule=new AuthorityRule(); | |
108 | + return rule; | |
109 | + } | |
110 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/entity/ParamFlowRuleCorrectEntity.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.entity; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity; | |
4 | +import com.alibaba.csp.sentinel.slots.block.Rule; | |
5 | +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowClusterConfig; | |
6 | +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem; | |
7 | +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; | |
8 | + | |
9 | +import java.util.*; | |
10 | + | |
11 | +/** | |
12 | + * @author zyf | |
13 | + * @description 重写热点规则实体类,。查看sentinel-dashboard在自定义ParamFlowRuleNacosPublisher时候 推送的数据是ParamFlowRuleEntity。 客户端接收的ParamFlowRule类 | |
14 | + * @date 2022-04-13 | |
15 | + */ | |
16 | +public class ParamFlowRuleCorrectEntity implements RuleEntity { | |
17 | + | |
18 | + private Long id; | |
19 | + private String app; | |
20 | + private String ip; | |
21 | + private Integer port; | |
22 | + private String limitApp; | |
23 | + private String resource; | |
24 | + private Date gmtCreate; | |
25 | + | |
26 | + private int grade = 1; | |
27 | + private Integer paramIdx; | |
28 | + private double count; | |
29 | + private int controlBehavior = 0; | |
30 | + private int maxQueueingTimeMs = 0; | |
31 | + private int burstCount = 0; | |
32 | + private long durationInSec = 1L; | |
33 | + private List<ParamFlowItem> paramFlowItemList = new ArrayList(); | |
34 | + private Map<Object, Integer> hotItems = new HashMap(); | |
35 | + private boolean clusterMode = false; | |
36 | + private ParamFlowClusterConfig clusterConfig; | |
37 | + | |
38 | + public int getGrade() { | |
39 | + return grade; | |
40 | + } | |
41 | + | |
42 | + public void setGrade(int grade) { | |
43 | + this.grade = grade; | |
44 | + } | |
45 | + | |
46 | + public Integer getParamIdx() { | |
47 | + return paramIdx; | |
48 | + } | |
49 | + | |
50 | + public void setParamIdx(Integer paramIdx) { | |
51 | + this.paramIdx = paramIdx; | |
52 | + } | |
53 | + | |
54 | + public double getCount() { | |
55 | + return count; | |
56 | + } | |
57 | + | |
58 | + public void setCount(double count) { | |
59 | + this.count = count; | |
60 | + } | |
61 | + | |
62 | + public int getControlBehavior() { | |
63 | + return controlBehavior; | |
64 | + } | |
65 | + | |
66 | + public void setControlBehavior(int controlBehavior) { | |
67 | + this.controlBehavior = controlBehavior; | |
68 | + } | |
69 | + | |
70 | + public int getMaxQueueingTimeMs() { | |
71 | + return maxQueueingTimeMs; | |
72 | + } | |
73 | + | |
74 | + public void setMaxQueueingTimeMs(int maxQueueingTimeMs) { | |
75 | + this.maxQueueingTimeMs = maxQueueingTimeMs; | |
76 | + } | |
77 | + | |
78 | + public int getBurstCount() { | |
79 | + return burstCount; | |
80 | + } | |
81 | + | |
82 | + public void setBurstCount(int burstCount) { | |
83 | + this.burstCount = burstCount; | |
84 | + } | |
85 | + | |
86 | + public long getDurationInSec() { | |
87 | + return durationInSec; | |
88 | + } | |
89 | + | |
90 | + public void setDurationInSec(long durationInSec) { | |
91 | + this.durationInSec = durationInSec; | |
92 | + } | |
93 | + | |
94 | + public List<ParamFlowItem> getParamFlowItemList() { | |
95 | + return paramFlowItemList; | |
96 | + } | |
97 | + | |
98 | + public void setParamFlowItemList(List<ParamFlowItem> paramFlowItemList) { | |
99 | + this.paramFlowItemList = paramFlowItemList; | |
100 | + } | |
101 | + | |
102 | + public Map<Object, Integer> getHotItems() { | |
103 | + return hotItems; | |
104 | + } | |
105 | + | |
106 | + public void setHotItems(Map<Object, Integer> hotItems) { | |
107 | + this.hotItems = hotItems; | |
108 | + } | |
109 | + | |
110 | + public boolean isClusterMode() { | |
111 | + return clusterMode; | |
112 | + } | |
113 | + | |
114 | + public void setClusterMode(boolean clusterMode) { | |
115 | + this.clusterMode = clusterMode; | |
116 | + } | |
117 | + | |
118 | + public ParamFlowClusterConfig getClusterConfig() { | |
119 | + return clusterConfig; | |
120 | + } | |
121 | + | |
122 | + public void setClusterConfig(ParamFlowClusterConfig clusterConfig) { | |
123 | + this.clusterConfig = clusterConfig; | |
124 | + } | |
125 | + | |
126 | + @Override | |
127 | + public Date getGmtCreate() { | |
128 | + return gmtCreate; | |
129 | + } | |
130 | + | |
131 | + public void setGmtCreate(Date gmtCreate) { | |
132 | + this.gmtCreate = gmtCreate; | |
133 | + } | |
134 | + | |
135 | + @Override | |
136 | + public Long getId() { | |
137 | + return id; | |
138 | + } | |
139 | + | |
140 | + @Override | |
141 | + public void setId(Long id) { | |
142 | + this.id = id; | |
143 | + } | |
144 | + | |
145 | + @Override | |
146 | + public String getApp() { | |
147 | + return app; | |
148 | + } | |
149 | + | |
150 | + public void setApp(String app) { | |
151 | + this.app = app; | |
152 | + } | |
153 | + | |
154 | + @Override | |
155 | + public String getIp() { | |
156 | + return ip; | |
157 | + } | |
158 | + | |
159 | + public void setIp(String ip) { | |
160 | + this.ip = ip; | |
161 | + } | |
162 | + | |
163 | + @Override | |
164 | + public Integer getPort() { | |
165 | + return port; | |
166 | + } | |
167 | + | |
168 | + public void setPort(Integer port) { | |
169 | + this.port = port; | |
170 | + } | |
171 | + | |
172 | + public String getLimitApp() { | |
173 | + return limitApp; | |
174 | + } | |
175 | + | |
176 | + public void setLimitApp(String limitApp) { | |
177 | + this.limitApp = limitApp; | |
178 | + } | |
179 | + | |
180 | + public String getResource() { | |
181 | + return resource; | |
182 | + } | |
183 | + | |
184 | + public void setResource(String resource) { | |
185 | + this.resource = resource; | |
186 | + } | |
187 | + | |
188 | + @Override | |
189 | + public Rule toRule() { | |
190 | + ParamFlowRule rule = new ParamFlowRule(); | |
191 | + return rule; | |
192 | + } | |
193 | +} | |
194 | + | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/flow/FlowRuleNacosProvider.java
0 → 100644
1 | +/* | |
2 | + * Copyright 1999-2018 Alibaba Group Holding Ltd. | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; | |
17 | + | |
18 | +import java.util.ArrayList; | |
19 | +import java.util.List; | |
20 | + | |
21 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
22 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
23 | +import org.springframework.beans.factory.annotation.Autowired; | |
24 | +import org.springframework.stereotype.Component; | |
25 | + | |
26 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | |
27 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
28 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
29 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
30 | +import com.alibaba.nacos.api.config.ConfigService; | |
31 | + | |
32 | +/** | |
33 | + * 流控规则拉取 | |
34 | + * | |
35 | + * @author zyf | |
36 | + * @date 2022-04-13 | |
37 | + */ | |
38 | +@Component("flowRuleNacosProvider") | |
39 | +public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> { | |
40 | + | |
41 | + @Autowired | |
42 | + private ConfigService configService; | |
43 | + @Autowired | |
44 | + private Converter<String, List<FlowRuleEntity>> converter; | |
45 | + | |
46 | + @Override | |
47 | + public List<FlowRuleEntity> getRules(String appName) throws Exception { | |
48 | + String rules = configService.getConfig(appName + SentinelConStants.FLOW_DATA_ID_POSTFIX, | |
49 | + SentinelConStants.GROUP_ID, 3000); | |
50 | + if (StringUtil.isEmpty(rules)) { | |
51 | + return new ArrayList<>(); | |
52 | + } | |
53 | + return converter.convert(rules); | |
54 | + } | |
55 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/flow/FlowRuleNacosPublisher.java
0 → 100644
1 | +/* | |
2 | + * Copyright 1999-2018 Alibaba Group Holding Ltd. | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; | |
17 | + | |
18 | +import java.util.List; | |
19 | + | |
20 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
21 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
22 | +import org.springframework.beans.factory.annotation.Autowired; | |
23 | +import org.springframework.stereotype.Component; | |
24 | + | |
25 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | |
26 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
27 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
28 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
29 | +import com.alibaba.nacos.api.config.ConfigService; | |
30 | + | |
31 | +/** | |
32 | + * 流控规则推送 | |
33 | + * | |
34 | + * @author zyf | |
35 | + * @date 2022-04-13 | |
36 | + */ | |
37 | +@Component("flowRuleNacosPublisher") | |
38 | +public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> { | |
39 | + | |
40 | + @Autowired | |
41 | + private ConfigService configService; | |
42 | + @Autowired | |
43 | + private Converter<List<FlowRuleEntity>, String> converter; | |
44 | + | |
45 | + @Override | |
46 | + public void publish(String app, List<FlowRuleEntity> rules) throws Exception { | |
47 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
48 | + if (rules == null) { | |
49 | + return; | |
50 | + } | |
51 | + configService.publishConfig(app + SentinelConStants.FLOW_DATA_ID_POSTFIX, | |
52 | + SentinelConStants.GROUP_ID, converter.convert(rules)); | |
53 | + } | |
54 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/gateway/GateWayApiNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.gateway; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
6 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
7 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
8 | +import com.alibaba.nacos.api.config.ConfigService; | |
9 | +import org.springframework.beans.factory.annotation.Autowired; | |
10 | +import org.springframework.stereotype.Component; | |
11 | + | |
12 | +import java.util.ArrayList; | |
13 | +import java.util.List; | |
14 | +/** | |
15 | + * 网关API规则拉取 | |
16 | + * | |
17 | + * @author zyf | |
18 | + * @date 2022-04-13 | |
19 | + */ | |
20 | +@Component("gateWayApiNacosProvider") | |
21 | +public class GateWayApiNacosProvider implements DynamicRuleProvider<List<ApiDefinitionEntity>> { | |
22 | + @Autowired | |
23 | + private ConfigService configService; | |
24 | + @Autowired | |
25 | + private Converter<String , List<ApiDefinitionEntity>> converter; | |
26 | + @Override | |
27 | + public List<ApiDefinitionEntity> getRules(String appName) throws Exception { | |
28 | + String rules = configService.getConfig(appName+ SentinelConStants.GETEWAY_API_DATA_ID_POSTFIX | |
29 | + , SentinelConStants.GROUP_ID,3000); | |
30 | + if(StringUtil.isEmpty(rules)){ | |
31 | + return new ArrayList<>(); | |
32 | + } | |
33 | + return converter.convert(rules); | |
34 | + } | |
35 | +} | |
0 | 36 | \ No newline at end of file |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/gateway/GateWayApiNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.gateway; | |
2 | + | |
3 | + | |
4 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
5 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
7 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
8 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
9 | +import com.alibaba.nacos.api.config.ConfigService; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.springframework.stereotype.Component; | |
12 | + | |
13 | +import java.util.List; | |
14 | +/** | |
15 | + * 网关API规则推送 | |
16 | + * | |
17 | + * @author zyf | |
18 | + * @date 2022-04-13 | |
19 | + */ | |
20 | +@Component("gateWayApiNacosPublisher") | |
21 | +public class GateWayApiNacosPublisher implements DynamicRulePublisher<List<ApiDefinitionEntity>> { | |
22 | + @Autowired | |
23 | + private ConfigService configService; | |
24 | + @Autowired | |
25 | + private Converter<List<ApiDefinitionEntity>, String> converter; | |
26 | + @Override | |
27 | + public void publish(String app, List<ApiDefinitionEntity> rules) throws Exception { | |
28 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
29 | + if (rules == null) { | |
30 | + return; | |
31 | + } | |
32 | + configService.publishConfig(app+ SentinelConStants.GETEWAY_API_DATA_ID_POSTFIX, | |
33 | + SentinelConStants.GROUP_ID,converter.convert(rules)); | |
34 | + } | |
35 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/gateway/GateWayFlowRulesNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.gateway; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
7 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
8 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
9 | +import com.alibaba.nacos.api.config.ConfigService; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.springframework.stereotype.Component; | |
12 | + | |
13 | +import java.util.ArrayList; | |
14 | +import java.util.List; | |
15 | + | |
16 | +/** | |
17 | + * 网关流控规则拉取 | |
18 | + * | |
19 | + * @author zyf | |
20 | + * @date 2022-04-13 | |
21 | + */ | |
22 | +@Component("gateWayFlowRulesNacosProvider") | |
23 | +public class GateWayFlowRulesNacosProvider implements DynamicRuleProvider<List<GatewayFlowRuleEntity>> { | |
24 | + | |
25 | + @Autowired | |
26 | + private ConfigService configService; | |
27 | + @Autowired | |
28 | + private Converter<String, List<GatewayFlowRuleEntity>> converter; | |
29 | + | |
30 | + @Override | |
31 | + public List<GatewayFlowRuleEntity> getRules(String appName) throws Exception { | |
32 | + String rules = configService.getConfig(appName + SentinelConStants.GETEWAY_FLOW_DATA_ID_POSTFIX, | |
33 | + SentinelConStants.GROUP_ID, 3000); | |
34 | + if (StringUtil.isEmpty(rules)) { | |
35 | + return new ArrayList<>(); | |
36 | + } | |
37 | + return converter.convert(rules); | |
38 | + } | |
39 | + | |
40 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/gateway/GateWayFlowRulesNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.gateway; | |
2 | + | |
3 | + | |
4 | +import java.util.List; | |
5 | + | |
6 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
7 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
8 | +import org.springframework.beans.factory.annotation.Autowired; | |
9 | +import org.springframework.stereotype.Component; | |
10 | + | |
11 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | |
12 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
13 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
14 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
15 | +import com.alibaba.nacos.api.config.ConfigService; | |
16 | + | |
17 | +/** | |
18 | + * 网关流控规则推送 | |
19 | + * | |
20 | + * @author zyf | |
21 | + * @date 2022-04-13 | |
22 | + */ | |
23 | +@Component("gateWayFlowRulesNacosPublisher") | |
24 | +public class GateWayFlowRulesNacosPublisher implements DynamicRulePublisher<List<GatewayFlowRuleEntity>> { | |
25 | + | |
26 | + @Autowired | |
27 | + private ConfigService configService; | |
28 | + @Autowired | |
29 | + private Converter<List<GatewayFlowRuleEntity>, String> converter; | |
30 | + | |
31 | + | |
32 | + @Override | |
33 | + public void publish(String app, List<GatewayFlowRuleEntity> rules) throws Exception { | |
34 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
35 | + if (rules == null) { | |
36 | + return; | |
37 | + } | |
38 | + configService.publishConfig(app + SentinelConStants.GETEWAY_FLOW_DATA_ID_POSTFIX, | |
39 | + SentinelConStants.GROUP_ID, converter.convert(rules)); | |
40 | + } | |
41 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/paramflow/ParamFlowRuleNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.paramflow; | |
2 | + | |
3 | + | |
4 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
5 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
7 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
8 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.ParamFlowRuleCorrectEntity; | |
9 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
10 | +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; | |
11 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
12 | +import com.alibaba.nacos.api.config.ConfigService; | |
13 | +import org.springframework.beans.BeanUtils; | |
14 | +import org.springframework.beans.factory.annotation.Autowired; | |
15 | +import org.springframework.stereotype.Component; | |
16 | + | |
17 | +import java.util.ArrayList; | |
18 | +import java.util.List; | |
19 | +import java.util.stream.Collectors; | |
20 | + | |
21 | +/** | |
22 | + * 加载热点参数规则 | |
23 | + * | |
24 | + * @author zyf | |
25 | + * @date 2022-04-13 | |
26 | + */ | |
27 | +@Component("paramFlowRuleNacosProvider") | |
28 | +public class ParamFlowRuleNacosProvider implements DynamicRuleProvider<List<ParamFlowRuleEntity>> { | |
29 | + | |
30 | + @Autowired | |
31 | + private ConfigService configService; | |
32 | + @Autowired | |
33 | + private Converter<String, List<ParamFlowRuleCorrectEntity>> converter; | |
34 | + | |
35 | + @Override | |
36 | + public List<ParamFlowRuleEntity> getRules(String appName) throws Exception { | |
37 | + String rules = configService.getConfig(appName + SentinelConStants.PARAM_FLOW_DATA_ID_POSTFIX, | |
38 | + SentinelConStants.GROUP_ID, 3000); | |
39 | + if (StringUtil.isEmpty(rules)) { | |
40 | + return new ArrayList<>(); | |
41 | + } | |
42 | + List<ParamFlowRuleCorrectEntity> entityList = converter.convert(rules); | |
43 | + return entityList.stream().map(rule -> { | |
44 | + ParamFlowRule paramFlowRule = new ParamFlowRule(); | |
45 | + BeanUtils.copyProperties(rule, paramFlowRule); | |
46 | + ParamFlowRuleEntity entity = ParamFlowRuleEntity.fromParamFlowRule(rule.getApp(), rule.getIp(), rule.getPort(), paramFlowRule); | |
47 | + entity.setId(rule.getId()); | |
48 | + entity.setGmtCreate(rule.getGmtCreate()); | |
49 | + return entity; | |
50 | + }).collect(Collectors.toList()); | |
51 | + } | |
52 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/paramflow/ParamFlowRuleNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.paramflow; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
6 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.SentinelConfig; | |
7 | +import com.alibaba.csp.sentinel.dashboard.rule.nacos.entity.ParamFlowRuleCorrectEntity; | |
8 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
9 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
10 | +import com.alibaba.nacos.api.config.ConfigService; | |
11 | +import org.springframework.beans.BeanUtils; | |
12 | +import org.springframework.beans.factory.annotation.Autowired; | |
13 | +import org.springframework.stereotype.Component; | |
14 | + | |
15 | +import java.util.List; | |
16 | +import java.util.stream.Collectors; | |
17 | + | |
18 | +/** | |
19 | + * 持久化热点参数规则 | |
20 | + * | |
21 | + * @author zyf | |
22 | + * @date 2022-04-13 | |
23 | + */ | |
24 | +@Component("paramFlowRuleNacosPublisher") | |
25 | +public class ParamFlowRuleNacosPublisher implements DynamicRulePublisher<List<ParamFlowRuleEntity>> { | |
26 | + | |
27 | + @Autowired | |
28 | + private ConfigService configService; | |
29 | + @Autowired | |
30 | + private Converter<List<ParamFlowRuleCorrectEntity>, String> converter; | |
31 | + | |
32 | + @Override | |
33 | + public void publish(String app, List<ParamFlowRuleEntity> rules) throws Exception { | |
34 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
35 | + if (rules == null) { | |
36 | + return; | |
37 | + } | |
38 | + rules.forEach(e -> e.setApp(app)); | |
39 | + | |
40 | + // 转换 | |
41 | + List<ParamFlowRuleCorrectEntity> list = rules.stream().map(rule -> { | |
42 | + ParamFlowRuleCorrectEntity entity = new ParamFlowRuleCorrectEntity(); | |
43 | + BeanUtils.copyProperties(rule, entity); | |
44 | + return entity; | |
45 | + }).collect(Collectors.toList()); | |
46 | + | |
47 | + configService.publishConfig(app + SentinelConStants.PARAM_FLOW_DATA_ID_POSTFIX, | |
48 | + SentinelConStants.GROUP_ID, converter.convert(list)); | |
49 | + | |
50 | + } | |
51 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/system/SystemRuleNacosProvider.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.system; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | |
6 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
7 | +import com.alibaba.csp.sentinel.util.StringUtil; | |
8 | +import com.alibaba.nacos.api.config.ConfigService; | |
9 | +import org.springframework.beans.factory.annotation.Autowired; | |
10 | +import org.springframework.stereotype.Component; | |
11 | + | |
12 | +import java.util.ArrayList; | |
13 | +import java.util.List; | |
14 | + | |
15 | +/** | |
16 | + * 加载系统规则 | |
17 | + * | |
18 | + * @author zyf | |
19 | + * @date 2022-04-13 | |
20 | + */ | |
21 | +@Component("systemRuleNacosProvider") | |
22 | +public class SystemRuleNacosProvider implements DynamicRuleProvider<List<SystemRuleEntity>> { | |
23 | + @Autowired | |
24 | + private ConfigService configService; | |
25 | + @Autowired | |
26 | + private Converter<String, List<SystemRuleEntity>> converter; | |
27 | + | |
28 | + @Override | |
29 | + public List<SystemRuleEntity> getRules(String appName) throws Exception { | |
30 | + String rules = configService.getConfig(appName + SentinelConStants.SYSTEM_DATA_ID_POSTFIX, | |
31 | + SentinelConStants.GROUP_ID, 3000); | |
32 | + if (StringUtil.isEmpty(rules)) { | |
33 | + return new ArrayList<>(); | |
34 | + } | |
35 | + return converter.convert(rules); | |
36 | + } | |
37 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/system/SystemRuleNacosPublisher.java
0 → 100644
1 | +package com.alibaba.csp.sentinel.dashboard.rule.nacos.system; | |
2 | + | |
3 | +import com.alibaba.csp.sentinel.dashboard.constants.SentinelConStants; | |
4 | +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; | |
5 | +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | |
6 | +import com.alibaba.csp.sentinel.datasource.Converter; | |
7 | +import com.alibaba.csp.sentinel.util.AssertUtil; | |
8 | +import com.alibaba.nacos.api.config.ConfigService; | |
9 | +import org.springframework.beans.factory.annotation.Autowired; | |
10 | +import org.springframework.stereotype.Component; | |
11 | + | |
12 | +import java.util.List; | |
13 | + | |
14 | +/** | |
15 | + * 持久化系统规则 | |
16 | + * | |
17 | + * @author zyf | |
18 | + * @date 2022-04-13 | |
19 | + */ | |
20 | +@Component("systemRuleNacosPublisher") | |
21 | +public class SystemRuleNacosPublisher implements DynamicRulePublisher<List<SystemRuleEntity>> { | |
22 | + | |
23 | + @Autowired | |
24 | + private ConfigService configService; | |
25 | + @Autowired | |
26 | + private Converter<List<SystemRuleEntity>, String> converter; | |
27 | + | |
28 | + @Override | |
29 | + public void publish(String app, List<SystemRuleEntity> rules) throws Exception { | |
30 | + AssertUtil.notEmpty(app, "app name cannot be empty"); | |
31 | + if (rules == null) { | |
32 | + return; | |
33 | + } | |
34 | + configService.publishConfig(app + SentinelConStants.SYSTEM_DATA_ID_POSTFIX, | |
35 | + SentinelConStants.GROUP_ID, converter.convert(rules)); | |
36 | + } | |
37 | +} | |
... | ... |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/resources/application.properties deleted
1 | -#spring settings | |
2 | -spring.http.encoding.force=true | |
3 | -spring.http.encoding.charset=UTF-8 | |
4 | -spring.http.encoding.enabled=true | |
5 | - | |
6 | -#cookie name setting | |
7 | -server.servlet.session.cookie.name=sentinel_dashboard_cookie | |
8 | -#spring.cloud.nacos.config.server-addr=127.0.0.1:8848 | |
9 | -#spring.cloud.nacos.config.namespace= | |
10 | -#spring.cloud.nacos.config.group-id=DEFAULT_GROUP | |
11 | -server.port=8087 | |
12 | - | |
13 | -#logging settings | |
14 | -logging.level.org.springframework.web=INFO | |
15 | -logging.file=${user.home}/logs/csp/sentinel-dashboard.log | |
16 | -logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n | |
17 | -#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n | |
18 | - | |
19 | -#auth settings | |
20 | -auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version | |
21 | -auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png | |
22 | -# If auth.enabled=false, Sentinel console disable login | |
23 | -auth.username=sentinel | |
24 | -auth.password=sentinel | |
25 | - | |
26 | -# Inject the dashboard version. It's required to enable | |
27 | -# filtering in pom.xml for this resource file. | |
28 | -sentinel.dashboard.version=1.8.2 | |
29 | 0 | \ No newline at end of file |
jeecg-boot/jeecg-cloud-module/jeecg-cloud-sentinel/src/main/resources/application.yml
0 → 100644
1 | +server: | |
2 | + port: 9000 | |
3 | + servlet: | |
4 | + session: | |
5 | + cookie: | |
6 | + name: sentinel_dashboard_cookie | |
7 | + encoding: | |
8 | + charset: UTF-8 | |
9 | + enabled: true | |
10 | + force: true | |
11 | +spring: | |
12 | + mvc: | |
13 | + #Spring Boot 2.6+\u540E\u6620\u5C04\u5339\u914D\u7684\u9ED8\u8BA4\u7B56\u7565\u5DF2\u4ECEAntPathMatcher\u66F4\u6539\u4E3APathPatternParser,\u9700\u8981\u624B\u52A8\u6307\u5B9A\u4E3Aant-path-matcher | |
14 | + pathmatch: | |
15 | + matching-strategy: ant-path-matcher | |
16 | +#auth settings | |
17 | +auth: | |
18 | + filter: | |
19 | + exclude-url-suffixes: htm,html,js,css,map,ico,ttf,woff,png | |
20 | + exclude-urls: /,/auth/login,/auth/logout,/registry/machine,/version | |
21 | + password: sentinel | |
22 | + username: sentinel | |
23 | +logging: | |
24 | + level: | |
25 | + org: | |
26 | + springframework: | |
27 | + web: INFO | |
28 | + pattern: | |
29 | + file: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n' | |
30 | + file: | |
31 | + name: ${user.home}/logs/csp/sentinel-dashboard.log | |
32 | +nacos: | |
33 | + server: | |
34 | + ip: @config.server-addr@ | |
35 | + password: @config.password@ | |
36 | + username: @config.username@ | |
37 | +sentinel: | |
38 | + dashboard: | |
39 | + version: 1.8.2 | |
0 | 40 | \ No newline at end of file |
... | ... |