diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index 9f9a734e..baa1dba3 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -6,10 +6,17 @@ spring.cloud.sentinel.eager=true spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json spring.cloud.sentinel.datasource.ds1.file.data-type=json - -#spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json -#spring.cloud.sentinel.datasource.ds1.file.data-type=custom -#spring.cloud.sentinel.datasource.ds1.file.converter-class=org.springframework.cloud.alibaba.cloud.examples.JsonFlowRuleListConverter +spring.cloud.sentinel.datasource.ds1.file.rule-type=flow spring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json spring.cloud.sentinel.datasource.ds2.file.data-type=json +spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade + +spring.cloud.sentinel.datasource.ds3.file.file=classpath: authority.json +spring.cloud.sentinel.datasource.ds3.file.rule-type=authority + +spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json +spring.cloud.sentinel.datasource.ds4.file.rule-type=system + +spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json +spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json new file mode 100644 index 00000000..3fb4b249 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json @@ -0,0 +1,17 @@ +[ + { + "resource": "good", + "limitApp": "abc", + "strategy": 0 + }, + { + "resource": "bad", + "limitApp": "bcd", + "strategy": 1 + }, + { + "resource": "terrible", + "limitApp": "aaa", + "strategy": 1 + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json new file mode 100644 index 00000000..72e1c2dc --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json @@ -0,0 +1,16 @@ +[ + { + "resource": "hotResource", + "count": 0, + "grade": 1, + "limitApp": "default", + "paramIdx": 0, + "paramFlowItemList": [ + { + "object": "2", + "classType": "int", + "count": 1 + } + ] + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json new file mode 100644 index 00000000..7aa623a7 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json @@ -0,0 +1,8 @@ +[ + { + "highestSystemLoad": -1, + "qps": 100, + "avgRt": -1, + "maxThread": 10 + } +] diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java new file mode 100644 index 00000000..e59a5735 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java @@ -0,0 +1,81 @@ +package org.springframework.cloud.alibaba.sentinel.datasource; + +import java.util.Arrays; +import java.util.Optional; + +import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; +import org.springframework.util.StringUtils; + +import com.alibaba.csp.sentinel.slots.block.AbstractRule; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.system.SystemRule; + +/** + * Enum for {@link AbstractRule} class, using in + * {@link AbstractDataSourceProperties#ruleType} + * + * @author Jim + */ +public enum RuleType { + + /** + * flow + */ + FLOW("flow", FlowRule.class), + /** + * degrade + */ + DEGRADE("degrade", DegradeRule.class), + /** + * param flow + */ + PARAM_FLOW("param-flow", ParamFlowRule.class), + /** + * system + */ + SYSTEM("system", SystemRule.class), + /** + * authority + */ + AUTHORITY("authority", AuthorityRule.class); + + /** + * alias for {@link AbstractRule} + */ + private final String name; + + /** + * concrete {@link AbstractRule} class + */ + private final Class clazz; + + RuleType(String name, Class clazz) { + this.name = name; + this.clazz = clazz; + } + + public String getName() { + return name; + } + + public Class getClazz() { + return clazz; + } + + public static Optional getByName(String name) { + if (StringUtils.isEmpty(name)) { + return Optional.empty(); + } + return Arrays.stream(RuleType.values()) + .filter(ruleType -> name.equals(ruleType.getName())).findFirst(); + } + + public static Optional getByClass(Class clazz) { + return Arrays.stream(RuleType.values()) + .filter(ruleType -> clazz == ruleType.getClazz()).findFirst(); + } + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java index b8843537..0f74084e 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java @@ -1,5 +1,14 @@ package org.springframework.cloud.alibaba.sentinel.datasource.config; +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; + +import com.alibaba.csp.sentinel.datasource.AbstractDataSource; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; + import com.fasterxml.jackson.annotation.JsonIgnore; /** @@ -10,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; public class AbstractDataSourceProperties { private String dataType = "json"; + private RuleType ruleType; private String converterClass; @JsonIgnore protected String factoryBeanName; @@ -26,6 +36,14 @@ public class AbstractDataSourceProperties { this.dataType = dataType; } + public RuleType getRuleType() { + return ruleType; + } + + public void setRuleType(RuleType ruleType) { + this.ruleType = ruleType; + } + public String getConverterClass() { return converterClass; } @@ -42,8 +60,28 @@ public class AbstractDataSourceProperties { this.factoryBeanName = factoryBeanName; } - public void preCheck() { - + public void preCheck(String dataSourceName) { } + public void postRegister(AbstractDataSource dataSource) { + switch (this.getRuleType()) { + case FLOW: + FlowRuleManager.register2Property(dataSource.getProperty()); + break; + case DEGRADE: + DegradeRuleManager.register2Property(dataSource.getProperty()); + break; + case PARAM_FLOW: + ParamFlowRuleManager.register2Property(dataSource.getProperty()); + break; + case SYSTEM: + SystemRuleManager.register2Property(dataSource.getProperty()); + break; + case AUTHORITY: + AuthorityRuleManager.register2Property(dataSource.getProperty()); + break; + default: + break; + } + } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java index d6594c2b..19c24aaa 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java @@ -56,16 +56,17 @@ public class FileDataSourceProperties extends AbstractDataSourceProperties { } @Override - public void preCheck() { - super.preCheck(); + public void preCheck(String dataSourceName) { + super.preCheck(dataSourceName); try { this.setFile( ResourceUtils.getFile(StringUtils.trimAllWhitespace(this.getFile())) .getAbsolutePath()); } catch (IOException e) { - throw new RuntimeException("[Sentinel Starter] " + " handle file [" - + this.getFile() + "] error: " + e.getMessage(), e); + throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName + + " handle file [" + this.getFile() + "] error: " + e.getMessage(), + e); } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java index 88831102..1b49ac76 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java @@ -1,5 +1,6 @@ package org.springframework.cloud.alibaba.sentinel.datasource.config; +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceFactoryBean; import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceWithAuthorizationFactoryBean; @@ -29,7 +30,7 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { } @Override - public void preCheck() { + public void preCheck(String dataSourceName) { if (!StringUtils.isEmpty(System.getProperties() .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { this.setServerAddr(null); @@ -126,6 +127,12 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { result.setDataId(System.getProperties() .getProperty(SentinelDataSourceConstants.PROJECT_NAME) + "-" + type); result.setGroupId("nacos-sentinel"); + if (type.equals(RuleType.FLOW.getName())) { + result.setRuleType(RuleType.FLOW); + } + else { + result.setRuleType(RuleType.DEGRADE); + } return result; } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java index 5f64825b..ab4d2429 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java @@ -1,28 +1,11 @@ package org.springframework.cloud.alibaba.sentinel.datasource.converter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -36,133 +19,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @see ParamFlowRule * @see ObjectMapper */ -public class JsonConverter implements Converter> { +public class JsonConverter extends SentinelConverter { - private static final Logger logger = LoggerFactory.getLogger(JsonConverter.class); - - private final ObjectMapper objectMapper; - - public JsonConverter(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - @Override - public List convert(String source) { - List ruleList = new ArrayList<>(); - if (StringUtils.isEmpty(source)) { - logger.warn( - "Sentinel JsonConverter can not convert rules because source is empty"); - return ruleList; - } - try { - List jsonArray = objectMapper.readValue(source, - new TypeReference>() { - }); - jsonArray.stream().forEach(obj -> { - - String itemJson = null; - try { - itemJson = objectMapper.writeValueAsString(obj); - } - catch (JsonProcessingException e) { - // won't be happen - } - - List rules = Arrays.asList(convertFlowRule(itemJson), - convertDegradeRule(itemJson), convertSystemRule(itemJson), - convertAuthorityRule(itemJson), convertParamFlowRule(itemJson)); - - List convertRuleList = rules.stream() - .filter(rule -> !ObjectUtils.isEmpty(rule)) - .collect(Collectors.toList()); - - if (convertRuleList.size() == 0) { - logger.warn( - "Sentinel JsonConverter can not convert {} to any rules, ignore", - itemJson); - } - else if (convertRuleList.size() > 1) { - logger.warn( - "Sentinel JsonConverter convert {} and match multi rules, ignore", - itemJson); - } - else { - ruleList.add(convertRuleList.get(0)); - } - - }); - if (jsonArray.size() != ruleList.size()) { - logger.warn( - "Sentinel JsonConverter Source list size is not equals to Target List, maybe a " - + "part of json is invalid. Source List: " + jsonArray - + ", Target List: " + ruleList); - } - } - catch (Exception e) { - logger.error("Sentinel JsonConverter convert error: " + e.getMessage()); - throw new RuntimeException( - "Sentinel JsonConverter convert error: " + e.getMessage(), e); - } - return ruleList; - } - - private FlowRule convertFlowRule(String json) { - try { - FlowRule rule = objectMapper.readValue(json, FlowRule.class); - if (FlowRuleUtil.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private DegradeRule convertDegradeRule(String json) { - try { - DegradeRule rule = objectMapper.readValue(json, DegradeRule.class); - if (DegradeRuleManager.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private SystemRule convertSystemRule(String json) { - SystemRule rule = null; - try { - rule = objectMapper.readValue(json, SystemRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private AuthorityRule convertAuthorityRule(String json) { - AuthorityRule rule = null; - try { - rule = objectMapper.readValue(json, AuthorityRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private ParamFlowRule convertParamFlowRule(String json) { - ParamFlowRule rule = null; - try { - rule = objectMapper.readValue(json, ParamFlowRule.class); - } - catch (Exception e) { - // ignore - } - return rule; + public JsonConverter(ObjectMapper objectMapper, Class ruleClass) { + super(objectMapper, ruleClass); } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java new file mode 100644 index 00000000..f499a16c --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java @@ -0,0 +1,115 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.converter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; +import org.springframework.util.StringUtils; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.slots.block.AbstractRule; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.system.SystemRule; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Convert sentinel rules for json or xml array Using strict mode to parse json or xml + * + * @author Jim + * @see FlowRule + * @see DegradeRule + * @see SystemRule + * @see AuthorityRule + * @see ParamFlowRule + * @see ObjectMapper + */ +public abstract class SentinelConverter + implements Converter> { + + private static final Logger logger = LoggerFactory.getLogger(SentinelConverter.class); + + private final ObjectMapper objectMapper; + + private final Class ruleClass; + + public SentinelConverter(ObjectMapper objectMapper, Class ruleClass) { + this.objectMapper = objectMapper; + this.ruleClass = ruleClass; + } + + @Override + public List convert(String source) { + List ruleList = new ArrayList<>(); + if (StringUtils.isEmpty(source)) { + logger.warn("converter can not convert rules because source is empty"); + return ruleList; + } + try { + List sourceArray = objectMapper.readValue(source, + new TypeReference>() { + }); + sourceArray.stream().forEach(obj -> { + + String item = null; + try { + item = objectMapper.writeValueAsString(obj); + } + catch (JsonProcessingException e) { + // won't be happen + } + + Optional.ofNullable(convertRule(item)) + .ifPresent(convertRule -> ruleList.add(convertRule)); + }); + + if (ruleList.size() != sourceArray.size()) { + throw new IllegalArgumentException("convert " + ruleList.size() + + " rules but there are " + sourceArray.size() + + " rules from datasource. RuleClass: " + + ruleClass.getSimpleName()); + } + } + catch (Exception e) { + throw new RuntimeException("convert error: " + e.getMessage(), e); + } + return ruleList; + } + + private AbstractRule convertRule(String ruleStr) { + try { + final AbstractRule rule = objectMapper.readValue(ruleStr, ruleClass); + RuleType ruleType = RuleType.getByClass(ruleClass).get(); + switch (ruleType) { + case FLOW: + if (!FlowRuleUtil.isValidRule((FlowRule) rule)) { + return null; + } + break; + case DEGRADE: + if (!DegradeRuleManager.isValidRule((DegradeRule) rule)) { + return null; + } + default: + break; + } + return rule; + } + catch (Exception e) { + // ignore + } + return null; + } + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java index 77f3b593..6c8485d4 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java @@ -1,28 +1,12 @@ package org.springframework.cloud.alibaba.sentinel.datasource.converter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** @@ -34,134 +18,12 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; * @see SystemRule * @see AuthorityRule * @see ParamFlowRule + * @see ObjectMapper */ -public class XmlConverter implements Converter> { +public class XmlConverter extends SentinelConverter { - private static final Logger logger = LoggerFactory.getLogger(XmlConverter.class); - - private final XmlMapper xmlMapper; - - public XmlConverter(XmlMapper xmlMapper) { - this.xmlMapper = xmlMapper; - } - - @Override - public List convert(String source) { - List ruleList = new ArrayList<>(); - if (StringUtils.isEmpty(source)) { - logger.warn( - "Sentinel XmlConverter can not convert rules because source is empty"); - return ruleList; - } - try { - List xmlArray = xmlMapper.readValue(source, - new TypeReference>() { - }); - xmlArray.stream().forEach(obj -> { - - String itemXml = null; - try { - itemXml = xmlMapper.writeValueAsString(obj); - } - catch (JsonProcessingException e) { - // won't be happen - } - - List rules = Arrays.asList(convertFlowRule(itemXml), - convertDegradeRule(itemXml), convertSystemRule(itemXml), - convertAuthorityRule(itemXml), convertParamFlowRule(itemXml)); - - List convertRuleList = rules.stream() - .filter(rule -> !ObjectUtils.isEmpty(rule)) - .collect(Collectors.toList()); - - if (convertRuleList.size() == 0) { - logger.warn( - "Sentinel XmlConverter can not convert {} to any rules, ignore", - itemXml); - } - else if (convertRuleList.size() > 1) { - logger.warn( - "Sentinel XmlConverter convert {} and match multi rules, ignore", - itemXml); - } - else { - ruleList.add(convertRuleList.get(0)); - } - - }); - if (xmlArray.size() != ruleList.size()) { - logger.warn( - "Sentinel XmlConverter Source list size is not equals to Target List, maybe a " - + "part of xml is invalid. Source List: " + xmlArray - + ", Target List: " + ruleList); - } - } - catch (Exception e) { - logger.error("Sentinel XmlConverter convert error: " + e.getMessage()); - throw new RuntimeException( - "Sentinel XmlConverter convert error: " + e.getMessage(), e); - } - return ruleList; - } - - private FlowRule convertFlowRule(String xml) { - try { - FlowRule rule = xmlMapper.readValue(xml, FlowRule.class); - if (FlowRuleUtil.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private DegradeRule convertDegradeRule(String xml) { - try { - DegradeRule rule = xmlMapper.readValue(xml, DegradeRule.class); - if (DegradeRuleManager.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private SystemRule convertSystemRule(String xml) { - SystemRule rule = null; - try { - rule = xmlMapper.readValue(xml, SystemRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private AuthorityRule convertAuthorityRule(String xml) { - AuthorityRule rule = null; - try { - rule = xmlMapper.readValue(xml, AuthorityRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private ParamFlowRule convertParamFlowRule(String json) { - ParamFlowRule rule = null; - try { - rule = xmlMapper.readValue(json, ParamFlowRule.class); - } - catch (Exception e) { - // ignore - } - return rule; + public XmlConverter(XmlMapper xmlMapper, Class ruleClass) { + super(xmlMapper, ruleClass); } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java index 53347f7b..4349cf70 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java @@ -41,6 +41,11 @@ import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; import com.alibaba.csp.sentinel.config.SentinelConfig; import com.alibaba.csp.sentinel.init.InitExecutor; import com.alibaba.csp.sentinel.log.LogBase; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.alibaba.csp.sentinel.transport.config.TransportConfig; import com.alibaba.csp.sentinel.util.AppNameUtil; @@ -154,25 +159,67 @@ public class SentinelAutoConfiguration { return new SentinelDataSourceHandler(); } - @Bean("sentinel-json-converter") - public JsonConverter jsonConverter() { - return new JsonConverter(objectMapper()); - } + protected static class SentinelConverterConfiguration { + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Bean("sentinel-json-flow-converter") + public JsonConverter jsonFlowConverter() { + return new JsonConverter(objectMapper, FlowRule.class); + } + + @Bean("sentinel-json-degrade-converter") + public JsonConverter jsonDegradeConverter() { + return new JsonConverter(objectMapper, DegradeRule.class); + } + + @Bean("sentinel-json-system-converter") + public JsonConverter jsonSystemConverter() { + return new JsonConverter(objectMapper, SystemRule.class); + } + + @Bean("sentinel-json-authority-converter") + public JsonConverter jsonAuthorityConverter() { + return new JsonConverter(objectMapper, AuthorityRule.class); + } + + @Bean("sentinel-json-param-flow-converter") + public JsonConverter jsonParamFlowConverter() { + return new JsonConverter(objectMapper, ParamFlowRule.class); + } - private ObjectMapper objectMapper() { - return new ObjectMapper(); } @ConditionalOnClass(XmlMapper.class) protected static class SentinelXmlConfiguration { - @Bean("sentinel-xml-converter") - public XmlConverter xmlConverter() { - return new XmlConverter(xmlMapper()); + + private XmlMapper xmlMapper = new XmlMapper(); + + @Bean("sentinel-xml-flow-converter") + public XmlConverter xmlFlowConverter() { + return new XmlConverter(xmlMapper, FlowRule.class); } - private XmlMapper xmlMapper() { - return new XmlMapper(); + @Bean("sentinel-xml-degrade-converter") + public XmlConverter xmlDegradeConverter() { + return new XmlConverter(xmlMapper, DegradeRule.class); } + + @Bean("sentinel-xml-system-converter") + public XmlConverter xmlSystemConverter() { + return new XmlConverter(xmlMapper, SystemRule.class); + } + + @Bean("sentinel-xml-authority-converter") + public XmlConverter xmlAuthorityConverter() { + return new XmlConverter(xmlMapper, AuthorityRule.class); + } + + @Bean("sentinel-xml-param-flow-converter") + public XmlConverter xmlParamFlowConverter() { + return new XmlConverter(xmlMapper, ParamFlowRule.class); + } + } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java index 6a5feca4..f9776d27 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.TreeMap; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,17 +31,9 @@ import org.springframework.util.StringUtils; import com.alibaba.csp.sentinel.datasource.AbstractDataSource; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.property.SentinelProperty; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.AbstractRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; -import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; /** * Sentinel {@link ReadableDataSource} Handler Handle the configurations of @@ -60,9 +51,6 @@ public class SentinelDataSourceHandler { private List dataTypeList = Arrays.asList("json", "xml"); - private List rulesList = Arrays.asList(FlowRule.class, DegradeRule.class, - SystemRule.class, AuthorityRule.class, ParamFlowRule.class); - private List dataSourceBeanNameList = Collections .synchronizedList(new ArrayList<>()); @@ -102,55 +90,26 @@ public class SentinelDataSourceHandler { sentinelProperties.getDatasource() .forEach((dataSourceName, dataSourceProperties) -> { - List validFields = dataSourceProperties.getValidField(); - if (validFields.size() != 1) { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " multi datasource active and won't loaded: " - + dataSourceProperties.getValidField()); - return; + try { + List validFields = dataSourceProperties.getValidField(); + if (validFields.size() != 1) { + logger.error("[Sentinel Starter] DataSource " + dataSourceName + + " multi datasource active and won't loaded: " + + dataSourceProperties.getValidField()); + return; + } + AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties + .getValidDataSourceProperties(); + abstractDataSourceProperties.preCheck(dataSourceName); + registerBean(beanFactory, abstractDataSourceProperties, + dataSourceName + "-sentinel-" + validFields.get(0) + + "-datasource"); + } + catch (Exception e) { + logger.error("[Sentinel Starter] DataSource " + dataSourceName + + " build error: " + e.getMessage(), e); } - - AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties - .getValidDataSourceProperties(); - abstractDataSourceProperties.preCheck(); - registerBean(beanFactory, abstractDataSourceProperties, dataSourceName - + "-sentinel-" + validFields.get(0) + "-datasource"); }); - - dataSourceBeanNameList.forEach(beanName -> { - ReadableDataSource dataSource = beanFactory.getBean(beanName, - ReadableDataSource.class); - Object ruleConfig; - try { - logger.info("[Sentinel Starter] DataSource " + beanName - + " start to loadConfig"); - ruleConfig = dataSource.loadConfig(); - } - catch (Exception e) { - logger.error("[Sentinel Starter] DataSource " + beanName - + " loadConfig error: " + e.getMessage(), e); - return; - } - SentinelProperty sentinelProperty = dataSource.getProperty(); - Class ruleType = getAndCheckRuleType(ruleConfig, beanName); - if (ruleType != null) { - if (ruleType == FlowRule.class) { - FlowRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == DegradeRule.class) { - DegradeRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == SystemRule.class) { - SystemRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == AuthorityRule.class) { - AuthorityRuleManager.register2Property(sentinelProperty); - } - else { - ParamFlowRuleManager.register2Property(sentinelProperty); - } - } - }); } private void registerBean(DefaultListableBeanFactory beanFactory, @@ -236,9 +195,11 @@ public class SentinelDataSourceHandler { } // converter type now support xml or json. // The bean name of these converters wrapped by - // 'sentinel-{converterType}-converter' + // 'sentinel-{converterType}-{ruleType}-converter' builder.addPropertyReference("converter", - "sentinel-" + propertyValue.toString() + "-converter"); + "sentinel-" + propertyValue.toString() + "-" + + dataSourceProperties.getRuleType().getName() + + "-converter"); } } else if (CONVERTERCLASS_FIELD.equals(propertyName)) { @@ -256,6 +217,13 @@ public class SentinelDataSourceHandler { // init in Spring AbstractDataSource newDataSource = (AbstractDataSource) beanFactory .getBean(dataSourceName); + + logAndCheckRuleType(newDataSource, dataSourceName, + dataSourceProperties.getRuleType().getClazz()); + + // register property in RuleManager + dataSourceProperties.postRegister(newDataSource); + // commercialization if (!StringUtils.isEmpty(System.getProperties() .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { @@ -269,55 +237,50 @@ public class SentinelDataSourceHandler { dataSourceBeanNameList.add(dataSourceName); } - private Class getAndCheckRuleType(Object ruleConfig, String dataSourceName) { - if (rulesList.contains(ruleConfig.getClass())) { - logger.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName, 1, - ruleConfig.getClass().getSimpleName()); - return ruleConfig.getClass(); + private void logAndCheckRuleType(AbstractDataSource dataSource, String dataSourceName, + Class ruleClass) { + Object ruleConfig; + try { + ruleConfig = dataSource.loadConfig(); } - else if (ruleConfig instanceof List) { + catch (Exception e) { + logger.error("[Sentinel Starter] DataSource " + dataSourceName + + " loadConfig error: " + e.getMessage(), e); + return; + } + if (ruleConfig instanceof List) { List convertedRuleList = (List) ruleConfig; if (CollectionUtils.isEmpty(convertedRuleList)) { logger.warn("[Sentinel Starter] DataSource {} rule list is empty.", dataSourceName); - return null; + return; } if (convertedRuleList.stream() - .allMatch(rule -> rulesList.contains(rule.getClass()))) { - if (rulesList.contains(convertedRuleList.get(0).getClass()) - && convertedRuleList.stream() - .filter(rule -> rule.getClass() == convertedRuleList - .get(0).getClass()) - .toArray().length == convertedRuleList.size()) { - logger.info("[Sentinel Starter] DataSource {} load {} {}", - dataSourceName, convertedRuleList.size(), - convertedRuleList.get(0).getClass().getSimpleName()); - return convertedRuleList.get(0).getClass(); - } - else { - logger.warn( - "[Sentinel Starter] DataSource {} all rules are not same rule type and it will not be used. " - + "Rule List: {}", - dataSourceName, convertedRuleList.toString()); - } + .noneMatch(rule -> rule.getClass() == ruleClass)) { + logger.error("[Sentinel Starter] DataSource {} none rules are {} type.", + dataSourceName, ruleClass.getSimpleName()); + throw new IllegalArgumentException("[Sentinel Starter] DataSource " + + dataSourceName + " none rules are " + ruleClass.getSimpleName() + + " type."); + } + else if (!convertedRuleList.stream() + .allMatch(rule -> rule.getClass() == ruleClass)) { + logger.warn("[Sentinel Starter] DataSource {} all rules are not {} type.", + dataSourceName, ruleClass.getSimpleName()); } else { - List classList = (List) convertedRuleList.stream() - .map(Object::getClass).collect(Collectors.toList()); - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class List: " + classList); - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class List: " + classList); + logger.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName, + convertedRuleList.size(), ruleClass.getSimpleName()); } } else { logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class: " + ruleConfig.getClass()); - throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class: " + ruleConfig.getClass()); + + " rule class is not List<" + ruleClass.getSimpleName() + + ">. Class: " + ruleConfig.getClass()); + throw new IllegalArgumentException("[Sentinel Starter] DataSource " + + dataSourceName + " rule class is not List<" + + ruleClass.getSimpleName() + ">. Class: " + ruleConfig.getClass()); } - return null; } public List getDataSourceBeanNameList() {