diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 48b69819..1ab8d95d 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -16,7 +16,7 @@ Spring Cloud Alibaba Dependencies - 1.4.0 + 1.4.1 3.1.0 0.8.1 0.1.3 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java index 94ef5dde..c9f82e3b 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java @@ -17,4 +17,4 @@ public class ExceptionUtil { return new SentinelClientHttpResponse("custom block info"); } -} +} \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java index f1fe28e6..c05c01af 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java @@ -26,7 +26,7 @@ public class ServiceApplication { } @Bean - public Converter myParser() { + public Converter myConverter() { return new JsonFlowRuleListConverter(); } 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 19c2868e..0f75d4b9 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 @@ -7,10 +7,22 @@ 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.rule-type=flow #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 \ No newline at end of file +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 \ No newline at end of file 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/pom.xml b/spring-cloud-alibaba-sentinel-datasource/pom.xml index b5e9217a..141236e1 100644 --- a/spring-cloud-alibaba-sentinel-datasource/pom.xml +++ b/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -83,13 +83,18 @@ true + + javax.validation + validation-api + true + + org.springframework.boot spring-boot-starter-test test - \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java deleted file mode 100644 index 6d63c401..00000000 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.alibaba.sentinel.datasource; - -import java.util.Properties; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; -import com.alibaba.csp.sentinel.datasource.AbstractDataSource; -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; -import com.alibaba.csp.sentinel.log.RecordLog; -import com.alibaba.csp.sentinel.util.StringUtil; -import com.alibaba.nacos.api.NacosFactory; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.config.listener.Listener; - -/** - * {@link NacosDataSource} now is not support ak、sk,namespace and endpoint. This class may - * be delete when {@link NacosDataSource} support commercialized - * - * @author Jim - */ -public class NacosDataSourceWithAuthorization extends AbstractDataSource { - - private static final int DEFAULT_TIMEOUT = 3000; - - private final ExecutorService pool = new ThreadPoolExecutor(1, 1, 0, - TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1), - new NamedThreadFactory("sentinel-nacos-auth-ds-update"), - new ThreadPoolExecutor.DiscardOldestPolicy()); - - private final Listener configListener; - private final Properties properties; - private final String dataId; - private final String groupId; - - private ConfigService configService = null; - - public NacosDataSourceWithAuthorization(final Properties properties, - final String groupId, final String dataId, Converter parser) { - super(parser); - if (StringUtil.isBlank(groupId) || StringUtil.isBlank(dataId)) { - throw new IllegalArgumentException(String - .format("Bad argument: groupId=[%s], dataId=[%s]", groupId, dataId)); - } - this.groupId = groupId; - this.dataId = dataId; - this.properties = properties; - this.configListener = new Listener() { - @Override - public Executor getExecutor() { - return pool; - } - - @Override - public void receiveConfigInfo(final String configInfo) { - RecordLog.info(String.format( - "[NacosDataSourceWithAuthorization] New property value received for %s", - properties.toString())); - T newValue = NacosDataSourceWithAuthorization.this.parser - .convert(configInfo); - // Update the new value to the property. - getProperty().updateValue(newValue); - } - }; - initNacosListener(); - loadInitialConfig(); - } - - private void loadInitialConfig() { - try { - T newValue = loadConfig(); - if (newValue == null) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] WARN: initial config is null, you may have to check your data source"); - } - getProperty().updateValue(newValue); - } - catch (Exception ex) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] Error when loading initial config", - ex); - } - } - - private void initNacosListener() { - try { - this.configService = NacosFactory.createConfigService(properties); - // Add config listener. - configService.addListener(dataId, groupId, configListener); - } - catch (Exception e) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] Error occurred when initializing Nacos data source", - e); - e.printStackTrace(); - } - } - - @Override - public String readSource() throws Exception { - if (configService == null) { - throw new IllegalStateException( - "Nacos config service has not been initialized or error occurred"); - } - return configService.getConfig(dataId, groupId, DEFAULT_TIMEOUT); - } - - @Override - public void close() { - if (configService != null) { - configService.removeListener(dataId, groupId, configListener); - } - pool.shutdownNow(); - } -} 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..e64c360c --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.alibaba.sentinel.datasource; + +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 RuleType getByName(String name) { + if (StringUtils.isEmpty(name)) { + return null; + } + for (RuleType ruleType : RuleType.values()) { + if (name.equals(ruleType.getName())) { + return ruleType; + } + } + return null; + } + + public static RuleType getByClass(Class clazz) { + for (RuleType ruleType : RuleType.values()) { + if (clazz.equals(ruleType.getClazz())) { + return ruleType; + } + } + return null; + } + +} \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java index 8903b700..345b443d 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java @@ -23,14 +23,4 @@ public interface SentinelDataSourceConstants { String PROPERTY_PREFIX = "spring.cloud.sentinel"; - String NACOS_DATASOURCE_AK = PROPERTY_PREFIX + ".nacos.config.access-key"; - - String NACOS_DATASOURCE_SK = PROPERTY_PREFIX + ".nacos.config.secret-key"; - - String NACOS_DATASOURCE_NAMESPACE = PROPERTY_PREFIX + ".nacos.config.namespace"; - - String NACOS_DATASOURCE_ENDPOINT = PROPERTY_PREFIX + ".nacos.config.endpoint"; - - String PROJECT_NAME = PROPERTY_PREFIX + ".nacos.config.project-name"; - } 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..7b6f5a49 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,32 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + +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; /** @@ -9,10 +36,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore; */ public class AbstractDataSourceProperties { + @NotNull private String dataType = "json"; + @NotNull + private RuleType ruleType; private String converterClass; @JsonIgnore - protected String factoryBeanName; + private final String factoryBeanName; public AbstractDataSourceProperties(String factoryBeanName) { this.factoryBeanName = factoryBeanName; @@ -26,6 +56,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; } @@ -38,12 +76,29 @@ public class AbstractDataSourceProperties { return factoryBeanName; } - public void setFactoryBeanName(String factoryBeanName) { - 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; + } + } +} \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java index 28d803ea..acfb222e 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java @@ -1,5 +1,23 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean; /** @@ -10,7 +28,9 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloD */ public class ApolloDataSourceProperties extends AbstractDataSourceProperties { + @NotNull private String namespaceName; + @NotNull private String flowRulesKey; private String defaultFlowRuleValue; diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java index ccd1b9b1..1f270cca 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java @@ -4,6 +4,8 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import javax.validation.Valid; + import org.springframework.util.ObjectUtils; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -19,12 +21,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; */ public class DataSourcePropertiesConfiguration { + @Valid private FileDataSourceProperties file; + @Valid private NacosDataSourceProperties nacos; + @Valid private ZookeeperDataSourceProperties zk; + @Valid private ApolloDataSourceProperties apollo; public DataSourcePropertiesConfiguration() { 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..e1084260 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 @@ -1,7 +1,25 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.config; import java.io.IOException; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; @@ -14,6 +32,7 @@ import org.springframework.util.StringUtils; */ public class FileDataSourceProperties extends AbstractDataSourceProperties { + @NotNull private String file; private String charset = "utf-8"; private long recommendRefreshMs = 3000L; @@ -56,16 +75,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..fd5eb195 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,8 +1,24 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.config; -import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceFactoryBean; -import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceWithAuthorizationFactoryBean; import org.springframework.util.StringUtils; /** @@ -14,10 +30,12 @@ import org.springframework.util.StringUtils; public class NacosDataSourceProperties extends AbstractDataSourceProperties { private String serverAddr; - private String groupId; - private String dataId; - // commercialized usage + @NotNull + private String groupId = "DEFAULT_GROUP"; + + @NotNull + private String dataId; private String endpoint; private String namespace; @@ -29,20 +47,10 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { } @Override - public void preCheck() { - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - this.setServerAddr(null); - this.setFactoryBeanName( - NacosDataSourceWithAuthorizationFactoryBean.class.getName()); - this.setEndpoint(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT)); - this.setNamespace(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_NAMESPACE)); - this.setAccessKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_AK)); - this.setSecretKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_SK)); + public void preCheck(String dataSourceName) { + if (StringUtils.isEmpty(serverAddr) && acmPropertiesInvalid()) { + throw new IllegalArgumentException( + "NacosDataSource properties value not correct. serverAddr is empty but there is empty value in accessKey, secretKey, endpoint, namespace property"); } } @@ -102,30 +110,9 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { this.secretKey = secretKey; } - public static NacosDataSourceProperties buildFlowByEDAS() { - return buildByEDAS("flow"); + public boolean acmPropertiesInvalid() { + return StringUtils.isEmpty(endpoint) || StringUtils.isEmpty(accessKey) + || StringUtils.isEmpty(secretKey) || StringUtils.isEmpty(namespace); } - public static NacosDataSourceProperties buildDegradeByEDAS() { - return buildByEDAS("degrade"); - } - - public static NacosDataSourceProperties buildByEDAS(String type) { - NacosDataSourceProperties result = new NacosDataSourceProperties(); - result.setFactoryBeanName( - NacosDataSourceWithAuthorizationFactoryBean.class.getName()); - result.setEndpoint(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT)); - result.setNamespace(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_NAMESPACE)); - result.setAccessKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_AK)); - result.setSecretKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_SK)); - result.setDataType("json"); - result.setDataId(System.getProperties() - .getProperty(SentinelDataSourceConstants.PROJECT_NAME) + "-" + type); - result.setGroupId("nacos-sentinel"); - return result; - } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java index a1d61667..6138b872 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java @@ -1,5 +1,23 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean; /** @@ -14,6 +32,7 @@ public class ZookeeperDataSourceProperties extends AbstractDataSourceProperties super(ZookeeperDataSourceFactoryBean.class.getName()); } + @NotNull private String serverAddr; private String path; 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 e0275b15..bb60dc19 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,27 +1,27 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 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 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; /** @@ -35,138 +35,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>() { - }); - - for (Object obj : jsonArray) { - 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 = new ArrayList<>(); - - for (AbstractRule rule : rules) { - if (!ObjectUtils.isEmpty(rule)) { - convertRuleList.add(rule); - } - } - - 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..bcb246c8 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.alibaba.sentinel.datasource.converter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +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>() { + }); + + for (Object obj : sourceArray) { + String item = null; + try { + item = objectMapper.writeValueAsString(obj); + } + catch (JsonProcessingException e) { + // won't be happen + } + + AbstractRule rule = convertRule(item); + if (rule != null) { + ruleList.add(rule); + } + + } + + 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); + 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 20961058..710a0da5 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,27 +1,28 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 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 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; /** @@ -33,139 +34,12 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; * @see SystemRule * @see AuthorityRule * @see ParamFlowRule - * @see XmlMapper + * @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>() { - }); - - for (Object obj : xmlArray) { - 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 = new ArrayList<>(); - - for (AbstractRule rule : rules) { - if (!ObjectUtils.isEmpty(rule)) { - convertRuleList.add(rule); - } - } - - 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-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java index 51218912..8a51bc55 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -1,9 +1,29 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; +import java.util.Properties; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.util.StringUtils; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; - -import org.springframework.beans.factory.FactoryBean; +import com.alibaba.nacos.api.PropertyKeyConst; /** * A {@link FactoryBean} for creating {@link NacosDataSource} instance. @@ -13,55 +33,104 @@ import org.springframework.beans.factory.FactoryBean; */ public class NacosDataSourceFactoryBean implements FactoryBean { - private String serverAddr; - private String groupId; - private String dataId; - private Converter converter; + private String serverAddr; + private String groupId; + private String dataId; + private Converter converter; - @Override - public NacosDataSource getObject() throws Exception { - return new NacosDataSource(serverAddr, groupId, dataId, converter); - } + private String endpoint; + private String namespace; + private String accessKey; + private String secretKey; - @Override - public Class getObjectType() { - return NacosDataSource.class; - } + @Override + public NacosDataSource getObject() throws Exception { + Properties properties = new Properties(); + if (!StringUtils.isEmpty(this.serverAddr)) { + properties.setProperty(PropertyKeyConst.SERVER_ADDR, this.serverAddr); + } + else { + properties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey); + properties.setProperty(PropertyKeyConst.SECRET_KEY, this.secretKey); + properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint); + } + if (!StringUtils.isEmpty(this.namespace)) { + properties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace); + } + return new NacosDataSource(properties, groupId, dataId, converter); + } - @Override - public boolean isSingleton() { - return true; - } + @Override + public boolean isSingleton() { + return true; + } - public String getServerAddr() { - return serverAddr; - } + @Override + public Class getObjectType() { + return NacosDataSource.class; + } - public void setServerAddr(String serverAddr) { - this.serverAddr = serverAddr; - } + public String getServerAddr() { + return serverAddr; + } - public String getGroupId() { - return groupId; - } + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } - public void setGroupId(String groupId) { - this.groupId = groupId; - } + public String getGroupId() { + return groupId; + } - public String getDataId() { - return dataId; - } + public void setGroupId(String groupId) { + this.groupId = groupId; + } - public void setDataId(String dataId) { - this.dataId = dataId; - } + public String getDataId() { + return dataId; + } - public Converter getConverter() { - return converter; - } + public void setDataId(String dataId) { + this.dataId = dataId; + } - public void setConverter(Converter converter) { - this.converter = converter; - } + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter converter) { + this.converter = converter; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java deleted file mode 100644 index dabe65b9..00000000 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import java.util.Properties; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.cloud.alibaba.sentinel.datasource.NacosDataSourceWithAuthorization; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; -import com.alibaba.nacos.api.PropertyKeyConst; - -/** - * A {@link FactoryBean} for creating {@link NacosDataSource} instance. - * - * @author Jim - * @see NacosDataSource - */ -public class NacosDataSourceWithAuthorizationFactoryBean - implements FactoryBean { - - private String endpoint; - private String namespace; - private String accessKey; - private String secretKey; - - private String groupId; - private String dataId; - private Converter converter; - - @Override - public NacosDataSourceWithAuthorization getObject() throws Exception { - Properties properties = new Properties(); - properties.put(PropertyKeyConst.ACCESS_KEY, accessKey); - properties.put(PropertyKeyConst.SECRET_KEY, secretKey); - properties.put(PropertyKeyConst.NAMESPACE, namespace); - properties.put(PropertyKeyConst.ENDPOINT, endpoint); - return new NacosDataSourceWithAuthorization(properties, groupId, dataId, - converter); - } - - @Override - public Class getObjectType() { - return NacosDataSourceWithAuthorization.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getAccessKey() { - return accessKey; - } - - public void setAccessKey(String accessKey) { - this.accessKey = accessKey; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getDataId() { - return dataId; - } - - public void setDataId(String dataId) { - this.dataId = dataId; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter converter) { - this.converter = converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index bcfd5d6a..e855b287 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -52,6 +52,12 @@ true + + org.springframework.cloud + spring-cloud-commons + true + + com.alibaba.csp sentinel-parameter-flow-control diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java index aa6079ac..0c2a9d09 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java @@ -23,7 +23,10 @@ public interface SentinelConstants { String PROPERTY_PREFIX = "spring.cloud.sentinel"; - // commercialized + String BLOCK_TYPE = "block"; + String FALLBACK_TYPE = "fallback"; + + // commercialization String FLOW_DATASOURCE_NAME = "edas-flow"; String DEGRADE_DATASOURCE_NAME = "edas-degrade"; diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java index 3f174118..274d36de 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java @@ -20,77 +20,76 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; +import javax.validation.Valid; + import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration; import org.springframework.core.Ordered; +import org.springframework.validation.annotation.Validated; import com.alibaba.csp.sentinel.config.SentinelConfig; import com.alibaba.csp.sentinel.log.LogBase; import com.alibaba.csp.sentinel.transport.config.TransportConfig; /** + * {@link ConfigurationProperties} for Sentinel. + * * @author xiaojing * @author hengyunabc * @author jiashuai.xie * @author Jim */ @ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX) +@Validated public class SentinelProperties { /** - * earlier initialize heart-beat when the spring container starts when the - * transport dependency is on classpath ,the configuration is effective + * Earlier initialize heart-beat when the spring container starts when the transport + * dependency is on classpath, the configuration is effective. */ private boolean eager = false; /** - * enable sentinel auto configure, the default value is true + * Enable sentinel auto configure, the default value is true. */ private boolean enabled = true; /** - * configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper' + * Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'. */ + @Valid private Map datasource = new TreeMap<>( String.CASE_INSENSITIVE_ORDER); /** - * transport configuration about dashboard and client + * Transport configuration about dashboard and client. */ - @NestedConfigurationProperty private Transport transport = new Transport(); /** - * metric configuration about resource + * Metric configuration about resource. */ - @NestedConfigurationProperty private Metric metric = new Metric(); /** - * web servlet configuration when the application is web ,the configuration is - * effective + * Web servlet configuration when the application is web, the configuration is + * effective. */ - @NestedConfigurationProperty private Servlet servlet = new Servlet(); /** - * sentinel filter when the application is web ,the configuration is effective - * + * Sentinel filter when the application is web, the configuration is effective. */ - @NestedConfigurationProperty private Filter filter = new Filter(); /** - * flow configuration + * Sentinel Flow configuration. */ - @NestedConfigurationProperty private Flow flow = new Flow(); /** - * sentinel log configuration {@link LogBase} + * Sentinel log configuration {@link LogBase}. */ - @NestedConfigurationProperty private Log log = new Log(); public boolean isEager() { @@ -168,7 +167,7 @@ public class SentinelProperties { public static class Flow { /** - * the cold factor {@link SentinelConfig#COLD_FACTOR} + * The cold factor {@link SentinelConfig#COLD_FACTOR}. */ private String coldFactor = "3"; @@ -185,7 +184,7 @@ public class SentinelProperties { public static class Servlet { /** - * The process page when the flow control is triggered + * The process page when the flow control is triggered. */ private String blockPage; @@ -201,17 +200,17 @@ public class SentinelProperties { public static class Metric { /** - * the metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE} + * The metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE}. */ private String fileSingleSize; /** - * the total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT} + * The total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT}. */ private String fileTotalCount; /** - * charset when sentinel write or search metric file + * Charset when sentinel write or search metric file. * {@link SentinelConfig#CHARSET} */ private String charset = "UTF-8"; @@ -244,22 +243,28 @@ public class SentinelProperties { public static class Transport { /** - * sentinel api port,default value is 8719 {@link TransportConfig#SERVER_PORT} + * Sentinel api port, default value is 8719 {@link TransportConfig#SERVER_PORT}. */ private String port = "8719"; /** - * sentinel dashboard address, won't try to connect dashboard when address is - * empty {@link TransportConfig#CONSOLE_SERVER} + * Sentinel dashboard address, won't try to connect dashboard when address is + * empty {@link TransportConfig#CONSOLE_SERVER}. */ private String dashboard = ""; /** - * send heartbeat interval millisecond - * {@link TransportConfig#HEARTBEAT_INTERVAL_MS} + * Send heartbeat interval millisecond + * {@link TransportConfig#HEARTBEAT_INTERVAL_MS}. */ private String heartbeatIntervalMs; + /** + * Get heartbeat client local ip. If the client ip not configured, it will be the + * address of local host. + */ + private String clientIp; + public String getHeartbeatIntervalMs() { return heartbeatIntervalMs; } @@ -284,17 +289,24 @@ public class SentinelProperties { this.dashboard = dashboard; } + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } } public static class Filter { /** - * sentinel filter chain order. + * Sentinel filter chain order. */ private int order = Ordered.HIGHEST_PRECEDENCE; /** - * URL pattern for sentinel filter,default is /* + * URL pattern for sentinel filter, default is /* */ private List urlPatterns; @@ -318,12 +330,12 @@ public class SentinelProperties { public static class Log { /** - * sentinel log base dir + * Sentinel log base dir. */ private String dir; /** - * distinguish the log file by pid number + * Distinguish the log file by pid number. */ private boolean switchPid = false; diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java index ee8e9b8c..8cb957b2 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java @@ -21,8 +21,6 @@ import java.util.List; import javax.servlet.Filter; -import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +31,8 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; + /** * @author xiaojing */ @@ -42,38 +42,33 @@ import org.springframework.context.annotation.Configuration; @EnableConfigurationProperties(SentinelProperties.class) public class SentinelWebAutoConfiguration { - private static final Logger logger = LoggerFactory - .getLogger(SentinelWebAutoConfiguration.class); + private static final Logger logger = LoggerFactory + .getLogger(SentinelWebAutoConfiguration.class); - @Autowired - private SentinelProperties properties; + @Autowired + private SentinelProperties properties; - @Bean - public FilterRegistrationBean servletRequestListener() { - FilterRegistrationBean registration = new FilterRegistrationBean(); + @Bean + public FilterRegistrationBean servletRequestListener() { + FilterRegistrationBean registration = new FilterRegistrationBean(); - SentinelProperties.Filter filterConfig = properties.getFilter(); + SentinelProperties.Filter filterConfig = properties.getFilter(); - if (null == filterConfig) { - filterConfig = new SentinelProperties.Filter(); - properties.setFilter(filterConfig); - } + if (filterConfig.getUrlPatterns() == null + || filterConfig.getUrlPatterns().isEmpty()) { + List defaultPatterns = new ArrayList<>(); + defaultPatterns.add("/*"); + filterConfig.setUrlPatterns(defaultPatterns); + } - if (filterConfig.getUrlPatterns() == null - || filterConfig.getUrlPatterns().isEmpty()) { - List defaultPatterns = new ArrayList<>(); - defaultPatterns.add("/*"); - filterConfig.setUrlPatterns(defaultPatterns); - } + registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0])); + Filter filter = new CommonFilter(); + registration.setFilter(filter); + registration.setOrder(filterConfig.getOrder()); + logger.info("[Sentinel Starter] register Sentinel with urlPatterns: {}.", + filterConfig.getUrlPatterns()); + return registration; - registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0])); - Filter filter = new CommonFilter(); - registration.setFilter(filter); - registration.setOrder(filterConfig.getOrder()); - logger.info("[Sentinel Starter] register Sentinel with urlPatterns: {}.", - filterConfig.getUrlPatterns()); - return registration; - - } + } } \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java index 3a3b967f..42eeca3c 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java @@ -27,33 +27,33 @@ import com.alibaba.csp.sentinel.util.StringUtil; */ final class BlockClassRegistry { - private static final Map FALLBACK_MAP = new ConcurrentHashMap<>(); - private static final Map BLOCK_HANDLER_MAP = new ConcurrentHashMap<>(); + private static final Map FALLBACK_MAP = new ConcurrentHashMap<>(); + private static final Map BLOCK_HANDLER_MAP = new ConcurrentHashMap<>(); - static Method lookupFallback(Class clazz, String name) { - return FALLBACK_MAP.get(getKey(clazz, name)); - } + static Method lookupFallback(Class clazz, String name) { + return FALLBACK_MAP.get(getKey(clazz, name)); + } - static Method lookupBlockHandler(Class clazz, String name) { - return BLOCK_HANDLER_MAP.get(getKey(clazz, name)); - } + static Method lookupBlockHandler(Class clazz, String name) { + return BLOCK_HANDLER_MAP.get(getKey(clazz, name)); + } - static void updateFallbackFor(Class clazz, String name, Method method) { - if (clazz == null || StringUtil.isBlank(name)) { - throw new IllegalArgumentException("Bad argument"); - } - FALLBACK_MAP.put(getKey(clazz, name), method); - } + static void updateFallbackFor(Class clazz, String name, Method method) { + if (clazz == null || StringUtil.isBlank(name)) { + throw new IllegalArgumentException("Bad argument"); + } + FALLBACK_MAP.put(getKey(clazz, name), method); + } - static void updateBlockHandlerFor(Class clazz, String name, Method method) { - if (clazz == null || StringUtil.isBlank(name)) { - throw new IllegalArgumentException("Bad argument"); - } - BLOCK_HANDLER_MAP.put(getKey(clazz, name), method); - } + static void updateBlockHandlerFor(Class clazz, String name, Method method) { + if (clazz == null || StringUtil.isBlank(name)) { + throw new IllegalArgumentException("Bad argument"); + } + BLOCK_HANDLER_MAP.put(getKey(clazz, name), method); + } - private static String getKey(Class clazz, String name) { - return String.format("%s:%s", clazz.getCanonicalName(), name); - } + private static String getKey(Class clazz, String name) { + return String.format("%s:%s", clazz.getCanonicalName(), name); + } } 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 317d27c8..3c908bec 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 @@ -20,6 +20,7 @@ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -27,10 +28,12 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.cloud.alibaba.sentinel.SentinelProperties; import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter; import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; +import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser; import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler; import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner; import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; @@ -39,6 +42,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; @@ -47,6 +55,7 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** * @author xiaojing + * @author jiashuai.xie * @author Jim */ @Configuration @@ -66,8 +75,20 @@ public class SentinelAutoConfiguration { @Autowired(required = false) private UrlBlockHandler urlBlockHandler; + @Autowired(required = false) + private RequestOriginParser requestOriginParser; + @PostConstruct private void init() { + if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR)) + && StringUtils.hasText(properties.getLog().getDir())) { + System.setProperty(LogBase.LOG_DIR, properties.getLog().getDir()); + } + if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_NAME_USE_PID)) + && properties.getLog().isSwitchPid()) { + System.setProperty(LogBase.LOG_NAME_USE_PID, + String.valueOf(properties.getLog().isSwitchPid())); + } if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME)) && StringUtils.hasText(projectName)) { System.setProperty(AppNameUtil.APP_NAME, projectName); @@ -88,6 +109,11 @@ public class SentinelAutoConfiguration { System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS, properties.getTransport().getHeartbeatIntervalMs()); } + if (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_CLIENT_IP)) + && StringUtils.hasText(properties.getTransport().getClientIp())) { + System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, + properties.getTransport().getClientIp()); + } if (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET)) && StringUtils.hasText(properties.getMetric().getCharset())) { System.setProperty(SentinelConfig.CHARSET, @@ -110,30 +136,25 @@ public class SentinelAutoConfiguration { System.setProperty(SentinelConfig.COLD_FACTOR, properties.getFlow().getColdFactor()); } - if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR)) - && StringUtils.hasText(properties.getLog().getDir())) { - System.setProperty(LogBase.LOG_DIR, properties.getLog().getDir()); - } - if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_NAME_USE_PID)) - && properties.getLog().isSwitchPid()) { - System.setProperty(LogBase.LOG_NAME_USE_PID, - String.valueOf(properties.getLog().isSwitchPid())); - } - if (StringUtils.hasText(properties.getServlet().getBlockPage())) { WebServletConfig.setBlockPage(properties.getServlet().getBlockPage()); } + if (urlBlockHandler != null) { WebCallbackManager.setUrlBlockHandler(urlBlockHandler); } if (urlCleaner != null) { WebCallbackManager.setUrlCleaner(urlCleaner); } + if (requestOriginParser != null) { + WebCallbackManager.setRequestOriginParser(requestOriginParser); + } // earlier initialize if (properties.isEager()) { InitExecutor.doInit(); } + } @Bean @@ -145,34 +166,78 @@ public class SentinelAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - public SentinelBeanPostProcessor sentinelBeanPostProcessor() { - return new SentinelBeanPostProcessor(); + public SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); } @Bean - public SentinelDataSourceHandler sentinelDataSourceHandler() { - return new SentinelDataSourceHandler(); + public SentinelDataSourceHandler sentinelDataSourceHandler( + DefaultListableBeanFactory beanFactory) { + return new SentinelDataSourceHandler(beanFactory); } - @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/SentinelBeanPostProcessor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java index 4fb9a6cf..29674e96 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java @@ -16,21 +16,34 @@ package org.springframework.cloud.alibaba.sentinel.custom; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.cloud.alibaba.sentinel.SentinelConstants; import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; import org.springframework.context.ApplicationContext; import org.springframework.core.type.StandardMethodMetadata; +import org.springframework.core.type.classreading.MethodMetadataReadingVisitor; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; +import com.alibaba.csp.sentinel.slots.block.BlockException; + /** * PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for RestTemplate * @@ -40,8 +53,14 @@ import org.springframework.web.client.RestTemplate; */ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor { - @Autowired - private ApplicationContext applicationContext; + private static final Logger logger = LoggerFactory + .getLogger(SentinelBeanPostProcessor.class); + + private final ApplicationContext applicationContext; + + public SentinelBeanPostProcessor(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } private ConcurrentHashMap cache = new ConcurrentHashMap<>(); @@ -49,21 +68,113 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if (checkSentinelProtect(beanDefinition, beanType)) { - SentinelRestTemplate sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition - .getSource()).getIntrospectedMethod() - .getAnnotation(SentinelRestTemplate.class); + SentinelRestTemplate sentinelRestTemplate; + if (beanDefinition.getSource() instanceof StandardMethodMetadata) { + sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition + .getSource()).getIntrospectedMethod() + .getAnnotation(SentinelRestTemplate.class); + } + else { + sentinelRestTemplate = beanDefinition.getResolvedFactoryMethod() + .getAnnotation(SentinelRestTemplate.class); + } + // check class and method validation + checkSentinelRestTemplate(sentinelRestTemplate, beanName); cache.put(beanName, sentinelRestTemplate); } } + private void checkSentinelRestTemplate(SentinelRestTemplate sentinelRestTemplate, + String beanName) { + checkBlock4RestTemplate(sentinelRestTemplate.blockHandlerClass(), + sentinelRestTemplate.blockHandler(), beanName, + SentinelConstants.BLOCK_TYPE); + checkBlock4RestTemplate(sentinelRestTemplate.fallbackClass(), + sentinelRestTemplate.fallback(), beanName, + SentinelConstants.FALLBACK_TYPE); + } + + private void checkBlock4RestTemplate(Class blockClass, String blockMethod, + String beanName, String type) { + if (blockClass == void.class && StringUtils.isEmpty(blockMethod)) { + return; + } + if (blockClass != void.class && StringUtils.isEmpty(blockMethod)) { + logger.error( + "{} class attribute exists but {} method attribute is not exists in bean[{}]", + type, type, beanName); + throw new IllegalArgumentException(type + " class attribute exists but " + + type + " method attribute is not exists in bean[" + beanName + "]"); + } + else if (blockClass == void.class && !StringUtils.isEmpty(blockMethod)) { + logger.error( + "{} method attribute exists but {} class attribute is not exists in bean[{}]", + type, type, beanName); + throw new IllegalArgumentException(type + " method attribute exists but " + + type + " class attribute is not exists in bean[" + beanName + "]"); + } + Class[] args = new Class[] { HttpRequest.class, byte[].class, + ClientHttpRequestExecution.class, BlockException.class }; + + List argList = new ArrayList<>(); + for (Class argClazz : args) { + argList.add(argClazz.getSimpleName()); + } + String argsStr = Arrays.toString(argList.toArray()); + Method foundMethod = ClassUtils.getStaticMethod(blockClass, blockMethod, args); + if (foundMethod == null) { + logger.error( + "{} static method can not be found in bean[{}]. The right method signature is {}#{}{}, please check your class name, method name and arguments", + type, beanName, blockClass.getName(), blockMethod, argsStr); + throw new IllegalArgumentException(type + + " static method can not be found in bean[" + beanName + + "]. The right method signature is " + blockClass.getName() + "#" + + blockMethod + argsStr + + ", please check your class name, method name and arguments"); + } + + if (!ClientHttpResponse.class.isAssignableFrom(foundMethod.getReturnType())) { + logger.error( + "{} method return value in bean[{}] is not ClientHttpResponse: {}#{}{}", + type, beanName, blockClass.getName(), blockMethod, argsStr); + throw new IllegalArgumentException(type + " method return value in bean[" + + beanName + "] is not ClientHttpResponse: " + blockClass.getName() + + "#" + blockMethod + argsStr); + } + if (type.equals(SentinelConstants.BLOCK_TYPE)) { + BlockClassRegistry.updateBlockHandlerFor(blockClass, blockMethod, + foundMethod); + } + else { + BlockClassRegistry.updateFallbackFor(blockClass, blockMethod, foundMethod); + } + } + private boolean checkSentinelProtect(RootBeanDefinition beanDefinition, Class beanType) { return beanType == RestTemplate.class - && beanDefinition.getSource() instanceof StandardMethodMetadata + && (checkStandardMethodMetadata(beanDefinition) + || checkMethodMetadataReadingVisitor(beanDefinition)); + } + + private boolean checkStandardMethodMetadata(RootBeanDefinition beanDefinition) { + return beanDefinition.getSource() instanceof StandardMethodMetadata && ((StandardMethodMetadata) beanDefinition.getSource()) .isAnnotated(SentinelRestTemplate.class.getName()); } + private boolean checkMethodMetadataReadingVisitor(RootBeanDefinition beanDefinition) { + return beanDefinition.getSource() instanceof MethodMetadataReadingVisitor + && ((MethodMetadataReadingVisitor) beanDefinition.getSource()) + .isAnnotated(SentinelRestTemplate.class.getName()); + } + + @Override + public Object postProcessBeforeInitialization(Object o, String s) + throws BeansException { + return o; + } + @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { @@ -84,7 +195,7 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext .getBean(interceptorBeanName.toString(), SentinelProtectInterceptor.class); - restTemplate.getInterceptors().add(sentinelProtectInterceptor); + restTemplate.getInterceptors().add(0, sentinelProtectInterceptor); } return bean; } @@ -103,10 +214,4 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces interceptorBeanDefinition); } - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - } \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java new file mode 100644 index 00000000..a13acf8a --- /dev/null +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.alibaba.sentinel.custom; + +import org.springframework.context.annotation.Configuration; + +/** + * @author lengleng + *

+ * support @EnableCircuitBreaker ,Do nothing + */ +@Configuration +public class SentinelCircuitBreakerConfiguration { +} 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 8489c7d8..447629df 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 @@ -17,47 +17,29 @@ package org.springframework.cloud.alibaba.sentinel.custom; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.cloud.alibaba.sentinel.SentinelConstants; import org.springframework.cloud.alibaba.sentinel.SentinelProperties; -import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration; -import org.springframework.cloud.alibaba.sentinel.datasource.config.NacosDataSourceProperties; import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter; import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter; -import org.springframework.context.event.EventListener; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; 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.AbstractRule; -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.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 @@ -68,113 +50,53 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; * @see JsonConverter * @see XmlConverter */ -public class SentinelDataSourceHandler { +public class SentinelDataSourceHandler implements SmartInitializingSingleton { private static final Logger logger = LoggerFactory .getLogger(SentinelDataSourceHandler.class); private List dataTypeList = Arrays.asList("json", "xml"); - private List> rulesList = Arrays.asList(FlowRule.class, - DegradeRule.class, SystemRule.class, AuthorityRule.class, - ParamFlowRule.class); + private final String DATA_TYPE_FIELD = "dataType"; + private final String CUSTOM_DATA_TYPE = "custom"; + private final String CONVERTER_CLASS_FIELD = "converterClass"; - private List dataSourceBeanNameList = Collections - .synchronizedList(new ArrayList()); + private final DefaultListableBeanFactory beanFactory; - private final String DATATYPE_FIELD = "dataType"; - private final String CUSTOM_DATATYPE = "custom"; - private final String CONVERTERCLASS_FIELD = "converterClass"; + public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory) { + this.beanFactory = beanFactory; + } @Autowired private SentinelProperties sentinelProperties; - @EventListener(classes = ApplicationReadyEvent.class) - public void buildDataSource(ApplicationReadyEvent event) throws Exception { - - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) event - .getApplicationContext().getAutowireCapableBeanFactory(); - - // commercialization - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - Map newDataSourceMap = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - for (Map.Entry entry : sentinelProperties - .getDatasource().entrySet()) { - if (entry.getValue().getValidDataSourceProperties() - .getClass() != NacosDataSourceProperties.class) { - newDataSourceMap.put(entry.getKey(), entry.getValue()); - } - } - newDataSourceMap.put(SentinelConstants.FLOW_DATASOURCE_NAME, - new DataSourcePropertiesConfiguration( - NacosDataSourceProperties.buildFlowByEDAS())); - newDataSourceMap.put(SentinelConstants.DEGRADE_DATASOURCE_NAME, - new DataSourcePropertiesConfiguration( - NacosDataSourceProperties.buildDegradeByEDAS())); - sentinelProperties.setDatasource(newDataSourceMap); - } - - for (Map.Entry entry : sentinelProperties - .getDatasource().entrySet()) { - String dataSourceName = entry.getKey(); - DataSourcePropertiesConfiguration dataSourceProperties = entry.getValue(); - - 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(); - registerBean(beanFactory, abstractDataSourceProperties, - dataSourceName + "-sentinel-" + validFields.get(0) + "-datasource"); - - } - - for (String beanName : dataSourceBeanNameList) { - ReadableDataSource dataSource = beanFactory.getBean(beanName, - ReadableDataSource.class); - Object ruleConfig; + @Override + public void afterSingletonsInstantiated() { + for (String dataSourceName : sentinelProperties.getDatasource().keySet()) { + DataSourcePropertiesConfiguration dataSourceProperties = sentinelProperties + .getDatasource().get(dataSourceName); try { - logger.info("[Sentinel Starter] DataSource " + beanName - + " start to loadConfig"); - ruleConfig = dataSource.loadConfig(); + 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(abstractDataSourceProperties, dataSourceName + "-sentinel-" + + validFields.get(0) + "-datasource"); } 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); - } + logger.error("[Sentinel Starter] DataSource " + dataSourceName + + " build error: " + e.getMessage(), e); } } } - private void registerBean(DefaultListableBeanFactory beanFactory, - final AbstractDataSourceProperties dataSourceProperties, + private void registerBean(final AbstractDataSourceProperties dataSourceProperties, String dataSourceName) { Map propertyMap = new HashMap<>(); @@ -194,8 +116,9 @@ public class SentinelDataSourceHandler { e); } } - propertyMap.put(CONVERTERCLASS_FIELD, dataSourceProperties.getConverterClass()); - propertyMap.put(DATATYPE_FIELD, dataSourceProperties.getDataType()); + + propertyMap.put(CONVERTER_CLASS_FIELD, dataSourceProperties.getConverterClass()); + propertyMap.put(DATA_TYPE_FIELD, dataSourceProperties.getDataType()); BeanDefinitionBuilder builder = BeanDefinitionBuilder .genericBeanDefinition(dataSourceProperties.getFactoryBeanName()); @@ -205,166 +128,136 @@ public class SentinelDataSourceHandler { Object propertyValue = entry.getValue(); Field field = ReflectionUtils.findField(dataSourceProperties.getClass(), propertyName); - if (field != null) { - if (DATATYPE_FIELD.equals(propertyName)) { - String dataType = StringUtils - .trimAllWhitespace(propertyValue.toString()); - if (CUSTOM_DATATYPE.equals(dataType)) { - try { - if (StringUtils - .isEmpty(dataSourceProperties.getConverterClass())) { - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + "dataType is custom, please set converter-class " - + "property"); - } - // construct custom Converter with 'converterClass' - // configuration and register - String customConvertBeanName = "sentinel-" - + dataSourceProperties.getConverterClass(); - if (!beanFactory.containsBean(customConvertBeanName)) { - beanFactory.registerBeanDefinition(customConvertBeanName, - BeanDefinitionBuilder - .genericBeanDefinition( - Class.forName(dataSourceProperties - .getConverterClass())) - .getBeanDefinition()); - } - builder.addPropertyReference("converter", - customConvertBeanName); - } - catch (ClassNotFoundException e) { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " handle " - + dataSourceProperties.getClass().getSimpleName() - + " error, class name: " - + dataSourceProperties.getConverterClass()); - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + " handle " - + dataSourceProperties.getClass() - .getSimpleName() - + " error, class name: " - + dataSourceProperties.getConverterClass(), - e); - } - } - else { - if (!dataTypeList.contains(StringUtils - .trimAllWhitespace(propertyValue.toString()))) { + if (null == field) { + continue; + } + if (DATA_TYPE_FIELD.equals(propertyName)) { + String dataType = StringUtils.trimAllWhitespace(propertyValue.toString()); + if (CUSTOM_DATA_TYPE.equals(dataType)) { + try { + if (StringUtils + .isEmpty(dataSourceProperties.getConverterClass())) { throw new RuntimeException("[Sentinel Starter] DataSource " - + dataSourceName + " dataType: " + propertyValue - + " is not support now. please using these types: " - + dataTypeList.toString()); + + dataSourceName + + "dataType is custom, please set converter-class " + + "property"); } - // converter type now support xml or json. - // The bean name of these converters wrapped by - // 'sentinel-{converterType}-converter' - builder.addPropertyReference("converter", - "sentinel-" + propertyValue.toString() + "-converter"); + // construct custom Converter with 'converterClass' + // configuration and register + String customConvertBeanName = "sentinel-" + + dataSourceProperties.getConverterClass(); + if (!this.beanFactory.containsBean(customConvertBeanName)) { + this.beanFactory.registerBeanDefinition(customConvertBeanName, + BeanDefinitionBuilder + .genericBeanDefinition( + Class.forName(dataSourceProperties + .getConverterClass())) + .getBeanDefinition()); + } + builder.addPropertyReference("converter", customConvertBeanName); + } + catch (ClassNotFoundException e) { + logger.error("[Sentinel Starter] DataSource " + dataSourceName + + " handle " + + dataSourceProperties.getClass().getSimpleName() + + " error, class name: " + + dataSourceProperties.getConverterClass()); + throw new RuntimeException("[Sentinel Starter] DataSource " + + dataSourceName + " handle " + + dataSourceProperties.getClass().getSimpleName() + + " error, class name: " + + dataSourceProperties.getConverterClass(), e); } - } - else if (CONVERTERCLASS_FIELD.equals(propertyName)) { - continue; } else { - // wired properties - if (propertyValue != null) { - builder.addPropertyValue(propertyName, propertyValue); + if (!dataTypeList.contains( + StringUtils.trimAllWhitespace(propertyValue.toString()))) { + throw new RuntimeException("[Sentinel Starter] DataSource " + + dataSourceName + " dataType: " + propertyValue + + " is not support now. please using these types: " + + dataTypeList.toString()); } + // converter type now support xml or json. + // The bean name of these converters wrapped by + // 'sentinel-{converterType}-{ruleType}-converter' + builder.addPropertyReference("converter", + "sentinel-" + propertyValue.toString() + "-" + + dataSourceProperties.getRuleType().getName() + + "-converter"); + } + } + else if (CONVERTER_CLASS_FIELD.equals(propertyName)) { + continue; + } + else { + // wired properties + if (propertyValue != null) { + builder.addPropertyValue(propertyName, propertyValue); } } } - beanFactory.registerBeanDefinition(dataSourceName, builder.getBeanDefinition()); + this.beanFactory.registerBeanDefinition(dataSourceName, + builder.getBeanDefinition()); // init in Spring - AbstractDataSource newDataSource = (AbstractDataSource) beanFactory + AbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory .getBean(dataSourceName); - // commercialization - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - if (dataSourceName.contains(SentinelConstants.FLOW_DATASOURCE_NAME)) { - FlowRuleManager.register2Property(newDataSource.getProperty()); - } - else if (dataSourceName.contains(SentinelConstants.DEGRADE_DATASOURCE_NAME)) { - DegradeRuleManager.register2Property(newDataSource.getProperty()); - } - } - dataSourceBeanNameList.add(dataSourceName); + + logAndCheckRuleType(newDataSource, dataSourceName, + dataSourceProperties.getRuleType().getClazz()); + + // register property in RuleManager + dataSourceProperties.postRegister(newDataSource); } - 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 (checkRuleTypeValid(convertedRuleList)) { - if (checkAllRuleTypeSame(convertedRuleList)) { - 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()); + int matchCount = 0; + for (Object rule : convertedRuleList) { + if (rule.getClass() == ruleClass) { + matchCount++; } } + if (matchCount == 0) { + 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 (matchCount != convertedRuleList.size()) { + logger.warn("[Sentinel Starter] DataSource {} all rules are not {} type.", + dataSourceName, ruleClass.getSimpleName()); + } else { - List classList = new ArrayList<>(); - for (Object rule : convertedRuleList) { - classList.add(rule.getClass()); - } - 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; - } - - private boolean checkRuleTypeValid(List convertedRuleList) { - int matchCount = 0; - for (Object rule : convertedRuleList) { - if (rulesList.contains(rule.getClass())) { - matchCount++; - } - } - return matchCount == convertedRuleList.size(); - } - - private boolean checkAllRuleTypeSame(List convertedRuleList) { - int matchCount = 0; - for (Object rule : convertedRuleList) { - if (rulesList.contains(rule.getClass()) - && rule.getClass() == convertedRuleList.get(0).getClass()) { - matchCount++; - } - } - return matchCount == convertedRuleList.size(); - } - - public List getDataSourceBeanNameList() { - return dataSourceBeanNameList; } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java index a1ab9e22..49bd003f 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java @@ -17,9 +17,9 @@ package org.springframework.cloud.alibaba.sentinel.custom; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; -import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,7 +29,6 @@ import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.ClassUtils; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; @@ -37,19 +36,18 @@ import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; -import com.alibaba.csp.sentinel.util.StringUtil; /** * Interceptor using by SentinelRestTemplate * - * @author fangjian + * @author Jim */ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor { private static final Logger logger = LoggerFactory .getLogger(SentinelProtectInterceptor.class); - private SentinelRestTemplate sentinelRestTemplate; + private final SentinelRestTemplate sentinelRestTemplate; public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) { this.sentinelRestTemplate = sentinelRestTemplate; @@ -82,18 +80,7 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor throw new IllegalStateException(e); } else { - try { - return handleBlockException(request, body, execution, - (BlockException) e); - } - catch (Exception ex) { - if (ex instanceof IllegalStateException) { - throw (IllegalStateException) ex; - } - throw new IllegalStateException( - "sentinel handle BlockException error: " + ex.getMessage(), - ex); - } + return handleBlockException(request, body, execution, (BlockException) e); } } finally { @@ -109,84 +96,49 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor } private ClientHttpResponse handleBlockException(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution, BlockException ex) throws Exception { + ClientHttpRequestExecution execution, BlockException ex) { Object[] args = new Object[] { request, body, execution, ex }; // handle degrade if (isDegradeFailure(ex)) { - Method method = extractFallbackMethod(sentinelRestTemplate.fallback(), + Method fallbackMethod = extractFallbackMethod(sentinelRestTemplate.fallback(), sentinelRestTemplate.fallbackClass()); - if (method != null) { - return (ClientHttpResponse) method.invoke(null, args); + if (fallbackMethod != null) { + return methodInvoke(fallbackMethod, args); } else { return new SentinelClientHttpResponse(); } } - // handle block + // handle flow Method blockHandler = extractBlockHandlerMethod( sentinelRestTemplate.blockHandler(), sentinelRestTemplate.blockHandlerClass()); if (blockHandler != null) { - return (ClientHttpResponse) blockHandler.invoke(null, args); + return methodInvoke(blockHandler, args); } else { return new SentinelClientHttpResponse(); } } + private ClientHttpResponse methodInvoke(Method method, Object... args) { + try { + return (ClientHttpResponse) method.invoke(null, args); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + private Method extractFallbackMethod(String fallback, Class fallbackClass) { - if (StringUtil.isBlank(fallback) || fallbackClass == void.class) { - return null; - } - Method cachedMethod = BlockClassRegistry.lookupFallback(fallbackClass, fallback); - Class[] args = new Class[] { HttpRequest.class, byte[].class, - ClientHttpRequestExecution.class, BlockException.class }; - if (cachedMethod == null) { - cachedMethod = ClassUtils.getStaticMethod(fallbackClass, fallback, args); - if (cachedMethod != null) { - if (!ClientHttpResponse.class - .isAssignableFrom(cachedMethod.getReturnType())) { - throw new IllegalStateException(String.format( - "the return type of method [%s] in class [%s] is not ClientHttpResponse in degrade", - cachedMethod.getName(), fallbackClass.getCanonicalName())); - } - BlockClassRegistry.updateFallbackFor(fallbackClass, fallback, - cachedMethod); - } - else { - throw new IllegalStateException(String.format( - "Cannot find method [%s] in class [%s] with parameters %s in degrade", - fallback, fallbackClass.getCanonicalName(), Arrays.asList(args))); - } - } - return cachedMethod; + return BlockClassRegistry.lookupFallback(fallbackClass, fallback); } private Method extractBlockHandlerMethod(String block, Class blockClass) { - if (StringUtil.isBlank(block) || blockClass == void.class) { - return null; - } - Method cachedMethod = BlockClassRegistry.lookupBlockHandler(blockClass, block); - Class[] args = new Class[] { HttpRequest.class, byte[].class, - ClientHttpRequestExecution.class, BlockException.class }; - if (cachedMethod == null) { - cachedMethod = ClassUtils.getStaticMethod(blockClass, block, args); - if (cachedMethod != null) { - if (!ClientHttpResponse.class - .isAssignableFrom(cachedMethod.getReturnType())) { - throw new IllegalStateException(String.format( - "the return type of method [%s] in class [%s] is not ClientHttpResponse in flow control", - cachedMethod.getName(), blockClass.getCanonicalName())); - } - BlockClassRegistry.updateBlockHandlerFor(blockClass, block, cachedMethod); - } - else { - throw new IllegalStateException(String.format( - "Cannot find method [%s] in class [%s] with parameters %s in flow control", - block, blockClass.getCanonicalName(), Arrays.asList(args))); - } - } - return cachedMethod; + return BlockClassRegistry.lookupBlockHandler(blockClass, block); } private boolean isDegradeFailure(BlockException ex) { diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java index d7e3e9da..cbd8d044 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java @@ -17,24 +17,20 @@ package org.springframework.cloud.alibaba.sentinel.endpoint; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; import org.springframework.cloud.alibaba.sentinel.SentinelProperties; -import org.springframework.cloud.alibaba.sentinel.custom.SentinelDataSourceHandler; -import org.springframework.context.ApplicationContext; -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; +import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.log.LogBase; +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.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; +import com.alibaba.csp.sentinel.transport.config.TransportConfig; /** * Endpoint for Sentinel, contains ans properties and rules @@ -42,45 +38,39 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; */ public class SentinelEndpoint extends AbstractEndpoint> { - @Autowired - private SentinelProperties sentinelProperties; + private final SentinelProperties sentinelProperties; - @Autowired - private SentinelDataSourceHandler dataSourceHandler; - - @Autowired - private ApplicationContext applicationContext; - - public SentinelEndpoint() { + public SentinelEndpoint(SentinelProperties sentinelProperties) { super("sentinel"); + this.sentinelProperties = sentinelProperties; } @Override public Map invoke() { - Map result = new HashMap<>(); + final Map result = new HashMap<>(); + if (sentinelProperties.isEnabled()) { - List flowRules = FlowRuleManager.getRules(); - List degradeRules = DegradeRuleManager.getRules(); - List systemRules = SystemRuleManager.getRules(); - List paramFlowRules = ParamFlowRuleManager.getRules(); - result.put("properties", sentinelProperties); - result.put("FlowRules", flowRules); - result.put("DegradeRules", degradeRules); - result.put("SystemRules", systemRules); - result.put("ParamFlowRule", paramFlowRules); - result.put("datasources", new HashMap()); + result.put("logDir", LogBase.getLogBaseDir()); + result.put("logUsePid", LogBase.isLogNameUsePid()); + result.put("blockPage", WebServletConfig.getBlockPage()); + result.put("metricsFileSize", SentinelConfig.singleMetricFileSize()); + result.put("metricsFileCharset", SentinelConfig.charset()); + result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount()); + result.put("consoleServer", TransportConfig.getConsoleServer()); + result.put("clientIp", TransportConfig.getHeartbeatClientIp()); + result.put("heartbeatIntervalMs", TransportConfig.getHeartbeatIntervalMs()); + result.put("clientPort", TransportConfig.getPort()); + result.put("coldFactor", sentinelProperties.getFlow().getColdFactor()); + result.put("filter", sentinelProperties.getFilter()); + result.put("datasource", sentinelProperties.getDatasource()); - for (String dataSourceBeanName : dataSourceHandler.getDataSourceBeanNameList()) { - ReadableDataSource dataSource = applicationContext.getBean(dataSourceBeanName, - ReadableDataSource.class); - try { - ((HashMap) result.get("datasources")).put(dataSourceBeanName, - dataSource.loadConfig()); - } - catch (Exception e) { - ((HashMap) result.get("datasources")).put(dataSourceBeanName, - "load error: " + e.getMessage()); - } + final Map rules = new HashMap<>(); + result.put("rules", rules); + rules.put("flowRules", FlowRuleManager.getRules()); + rules.put("degradeRules", DegradeRuleManager.getRules()); + rules.put("systemRules", SystemRuleManager.getRules()); + rules.put("authorityRule", AuthorityRuleManager.getRules()); + rules.put("paramFlowRule", ParamFlowRuleManager.getRules()); } return result; } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java index 728347b4..b49fb20e 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java @@ -34,8 +34,8 @@ public class SentinelEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint("sentinel") - public SentinelEndpoint sentinelEndPoint() { - return new SentinelEndpoint(); + public SentinelEndpoint sentinelEndPoint(SentinelProperties sentinelProperties) { + return new SentinelEndpoint(sentinelProperties); } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java index 6de453d4..78282a19 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java @@ -16,13 +16,6 @@ package org.springframework.cloud.alibaba.sentinel.rest; -import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; -import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.client.AbstractClientHttpResponse; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -31,6 +24,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; +import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.client.AbstractClientHttpResponse; + /** * Using by {@link SentinelRestTemplate} and {@link SentinelProtectInterceptor} * @@ -41,7 +41,6 @@ public class SentinelClientHttpResponse extends AbstractClientHttpResponse { private String blockResponse = "RestTemplate request block by sentinel"; public SentinelClientHttpResponse() { - } public SentinelClientHttpResponse(String blockResponse) { diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json index d05b0863..b445fc6a 100644 --- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -18,6 +18,11 @@ "defaultValue": "8719", "description": "sentinel api port." }, + { + "name": "spring.cloud.sentinel.transport.clientIp", + "type": "java.lang.String", + "description": "sentinel client ip connect to dashboard." + }, { "name": "spring.cloud.sentinel.transport.dashboard", "type": "java.lang.String", diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories index 702bb5bb..181c30b8 100644 --- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories @@ -3,3 +3,6 @@ org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration + +org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\ +org.springframework.cloud.alibaba.sentinel.custom.SentinelCircuitBreakerConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java index eaa682ca..65fe21ce 100644 --- a/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java @@ -27,8 +27,12 @@ import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplat import org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration; import org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor; import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; +import org.springframework.cloud.alibaba.sentinel.rest.SentinelClientHttpResponse; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -109,8 +113,9 @@ public class SentinelAutoConfigurationTests { } static class ExceptionUtil { - public static void handleException(BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); + public static ClientHttpResponse handleException(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution, BlockException ex) { + return new SentinelClientHttpResponse("custom block info"); } } diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java deleted file mode 100644 index 9e64b835..00000000 --- a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.alicloud.context.sentinel; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.cloud.alicloud.context.Constants; -import org.springframework.cloud.alicloud.context.listener.AbstractOnceApplicationListener; - -import com.alibaba.cloud.context.edas.EdasChangeOrderConfiguration; -import com.alibaba.cloud.context.edas.EdasChangeOrderConfigurationFactory; - -/** - * @author Jim - */ -public class SentinelAliCloudListener - extends AbstractOnceApplicationListener { - - private static final Logger logger = LoggerFactory - .getLogger(SentinelAliCloudListener.class); - - @Override - protected void handleEvent(ApplicationEnvironmentPreparedEvent event) { - EdasChangeOrderConfiguration edasChangeOrderConfiguration = EdasChangeOrderConfigurationFactory - .getEdasChangeOrderConfiguration(); - logger.info("Sentinel Nacos datasource will" - + (edasChangeOrderConfiguration.isEdasManaged() ? " be " : " not be ") - + "changed by edas change order."); - if (!edasChangeOrderConfiguration.isEdasManaged()) { - return; - } - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_ENDPOINT, - edasChangeOrderConfiguration.getAddressServerDomain()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_NAMESPACE, - edasChangeOrderConfiguration.getTenantId()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_AK, - edasChangeOrderConfiguration.getDauthAccessKey()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_SK, - edasChangeOrderConfiguration.getDauthSecretKey()); - System.getProperties().setProperty(Constants.Sentinel.PROJECT_NAME, - edasChangeOrderConfiguration.getProjectName()); - } - - @Override - protected String conditionalOnClass() { - return "com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource"; - } - -} diff --git a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories index b39c6499..0679da54 100644 --- a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories @@ -11,5 +11,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.context.ApplicationListener=\ org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\ org.springframework.cloud.alicloud.context.nacos.NacosConfigParameterInitListener,\ - org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener,\ - org.springframework.cloud.alicloud.context.sentinel.SentinelAliCloudListener \ No newline at end of file + org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener \ No newline at end of file diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java deleted file mode 100644 index de2a5bc0..00000000 --- a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.alicloud.context.sentinel; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.springframework.cloud.alicloud.context.BaseAliCloudSpringApplication; -import org.springframework.cloud.alicloud.context.Constants; -import org.springframework.cloud.alicloud.utils.ChangeOrderUtils; - -import com.alibaba.cloud.context.edas.EdasChangeOrderConfigurationFactory; - -/** - * @author xiaolongzuo - */ -@PrepareForTest({ EdasChangeOrderConfigurationFactory.class, - SentinelAliCloudListener.class }) -public class SentinelAliCloudListenerTests extends BaseAliCloudSpringApplication { - - @BeforeClass - public static void setUp() { - ChangeOrderUtils.mockChangeOrder(); - } - - @Test - public void testNacosParameterInitListener() { - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_ENDPOINT)) - .isEqualTo("testDomain"); - assertThat(System.getProperty(Constants.Sentinel.PROJECT_NAME)) - .isEqualTo("testProjectName"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_NAMESPACE)) - .isEqualTo("testTenantId"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_AK)) - .isEqualTo("testAK"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_SK)) - .isEqualTo("testSK"); - - } -}