mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge pull request #361 from fangjian0423/1.x
sync sentinel to 1.x branch
This commit is contained in:
commit
5d69156395
@ -16,7 +16,7 @@
|
|||||||
<description>Spring Cloud Alibaba Dependencies</description>
|
<description>Spring Cloud Alibaba Dependencies</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<sentinel.version>1.4.0</sentinel.version>
|
<sentinel.version>1.4.1</sentinel.version>
|
||||||
<oss.version>3.1.0</oss.version>
|
<oss.version>3.1.0</oss.version>
|
||||||
<nacos.version>0.8.1</nacos.version>
|
<nacos.version>0.8.1</nacos.version>
|
||||||
<fescar.version>0.1.3</fescar.version>
|
<fescar.version>0.1.3</fescar.version>
|
||||||
|
@ -26,7 +26,7 @@ public class ServiceApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Converter myParser() {
|
public Converter myConverter() {
|
||||||
return new JsonFlowRuleListConverter();
|
return new JsonFlowRuleListConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.file=classpath: flowrule.json
|
||||||
spring.cloud.sentinel.datasource.ds1.file.data-type=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.file=classpath: flowrule.json
|
||||||
#spring.cloud.sentinel.datasource.ds1.file.data-type=custom
|
#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.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.file=classpath: degraderule.json
|
||||||
spring.cloud.sentinel.datasource.ds2.file.data-type=json
|
spring.cloud.sentinel.datasource.ds2.file.data-type=json
|
||||||
|
spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade
|
||||||
|
|
||||||
|
spring.cloud.sentinel.datasource.ds3.file.file=classpath: authority.json
|
||||||
|
spring.cloud.sentinel.datasource.ds3.file.rule-type=authority
|
||||||
|
|
||||||
|
spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json
|
||||||
|
spring.cloud.sentinel.datasource.ds4.file.rule-type=system
|
||||||
|
|
||||||
|
spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json
|
||||||
|
spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow
|
@ -0,0 +1,17 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"resource": "good",
|
||||||
|
"limitApp": "abc",
|
||||||
|
"strategy": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resource": "bad",
|
||||||
|
"limitApp": "bcd",
|
||||||
|
"strategy": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resource": "terrible",
|
||||||
|
"limitApp": "aaa",
|
||||||
|
"strategy": 1
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"resource": "hotResource",
|
||||||
|
"count": 0,
|
||||||
|
"grade": 1,
|
||||||
|
"limitApp": "default",
|
||||||
|
"paramIdx": 0,
|
||||||
|
"paramFlowItemList": [
|
||||||
|
{
|
||||||
|
"object": "2",
|
||||||
|
"classType": "int",
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,8 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"highestSystemLoad": -1,
|
||||||
|
"qps": 100,
|
||||||
|
"avgRt": -1,
|
||||||
|
"maxThread": 10
|
||||||
|
}
|
||||||
|
]
|
@ -83,13 +83,18 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
|
||||||
*/
|
|
||||||
public class NacosDataSourceWithAuthorization<T> extends AbstractDataSource<String, T> {
|
|
||||||
|
|
||||||
private static final int DEFAULT_TIMEOUT = 3000;
|
|
||||||
|
|
||||||
private final ExecutorService pool = new ThreadPoolExecutor(1, 1, 0,
|
|
||||||
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(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<String, T> 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,14 +23,4 @@ public interface SentinelDataSourceConstants {
|
|||||||
|
|
||||||
String PROPERTY_PREFIX = "spring.cloud.sentinel";
|
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";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
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;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,10 +36,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
*/
|
*/
|
||||||
public class AbstractDataSourceProperties {
|
public class AbstractDataSourceProperties {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private String dataType = "json";
|
private String dataType = "json";
|
||||||
|
@NotNull
|
||||||
|
private RuleType ruleType;
|
||||||
private String converterClass;
|
private String converterClass;
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
protected String factoryBeanName;
|
private final String factoryBeanName;
|
||||||
|
|
||||||
public AbstractDataSourceProperties(String factoryBeanName) {
|
public AbstractDataSourceProperties(String factoryBeanName) {
|
||||||
this.factoryBeanName = factoryBeanName;
|
this.factoryBeanName = factoryBeanName;
|
||||||
@ -26,6 +56,14 @@ public class AbstractDataSourceProperties {
|
|||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RuleType getRuleType() {
|
||||||
|
return ruleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRuleType(RuleType ruleType) {
|
||||||
|
this.ruleType = ruleType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getConverterClass() {
|
public String getConverterClass() {
|
||||||
return converterClass;
|
return converterClass;
|
||||||
}
|
}
|
||||||
@ -38,12 +76,29 @@ public class AbstractDataSourceProperties {
|
|||||||
return factoryBeanName;
|
return factoryBeanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFactoryBeanName(String factoryBeanName) {
|
public void preCheck(String dataSourceName) {
|
||||||
this.factoryBeanName = factoryBeanName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void preCheck() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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;
|
package org.springframework.cloud.alibaba.sentinel.datasource.config;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean;
|
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 {
|
public class ApolloDataSourceProperties extends AbstractDataSourceProperties {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private String namespaceName;
|
private String namespaceName;
|
||||||
|
@NotNull
|
||||||
private String flowRulesKey;
|
private String flowRulesKey;
|
||||||
private String defaultFlowRuleValue;
|
private String defaultFlowRuleValue;
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ import java.lang.reflect.Field;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
@ -19,12 +21,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
*/
|
*/
|
||||||
public class DataSourcePropertiesConfiguration {
|
public class DataSourcePropertiesConfiguration {
|
||||||
|
|
||||||
|
@Valid
|
||||||
private FileDataSourceProperties file;
|
private FileDataSourceProperties file;
|
||||||
|
|
||||||
|
@Valid
|
||||||
private NacosDataSourceProperties nacos;
|
private NacosDataSourceProperties nacos;
|
||||||
|
|
||||||
|
@Valid
|
||||||
private ZookeeperDataSourceProperties zk;
|
private ZookeeperDataSourceProperties zk;
|
||||||
|
|
||||||
|
@Valid
|
||||||
private ApolloDataSourceProperties apollo;
|
private ApolloDataSourceProperties apollo;
|
||||||
|
|
||||||
public DataSourcePropertiesConfiguration() {
|
public DataSourcePropertiesConfiguration() {
|
||||||
|
@ -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;
|
package org.springframework.cloud.alibaba.sentinel.datasource.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;
|
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -14,6 +32,7 @@ import org.springframework.util.StringUtils;
|
|||||||
*/
|
*/
|
||||||
public class FileDataSourceProperties extends AbstractDataSourceProperties {
|
public class FileDataSourceProperties extends AbstractDataSourceProperties {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private String file;
|
private String file;
|
||||||
private String charset = "utf-8";
|
private String charset = "utf-8";
|
||||||
private long recommendRefreshMs = 3000L;
|
private long recommendRefreshMs = 3000L;
|
||||||
@ -56,16 +75,17 @@ public class FileDataSourceProperties extends AbstractDataSourceProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preCheck() {
|
public void preCheck(String dataSourceName) {
|
||||||
super.preCheck();
|
super.preCheck(dataSourceName);
|
||||||
try {
|
try {
|
||||||
this.setFile(
|
this.setFile(
|
||||||
ResourceUtils.getFile(StringUtils.trimAllWhitespace(this.getFile()))
|
ResourceUtils.getFile(StringUtils.trimAllWhitespace(this.getFile()))
|
||||||
.getAbsolutePath());
|
.getAbsolutePath());
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException("[Sentinel Starter] " + " handle file ["
|
throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName
|
||||||
+ this.getFile() + "] error: " + e.getMessage(), e);
|
+ " handle file [" + this.getFile() + "] error: " + e.getMessage(),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
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.NacosDataSourceFactoryBean;
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceWithAuthorizationFactoryBean;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,10 +30,12 @@ import org.springframework.util.StringUtils;
|
|||||||
public class NacosDataSourceProperties extends AbstractDataSourceProperties {
|
public class NacosDataSourceProperties extends AbstractDataSourceProperties {
|
||||||
|
|
||||||
private String serverAddr;
|
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 endpoint;
|
||||||
private String namespace;
|
private String namespace;
|
||||||
@ -29,20 +47,10 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preCheck() {
|
public void preCheck(String dataSourceName) {
|
||||||
if (!StringUtils.isEmpty(System.getProperties()
|
if (StringUtils.isEmpty(serverAddr) && acmPropertiesInvalid()) {
|
||||||
.getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) {
|
throw new IllegalArgumentException(
|
||||||
this.setServerAddr(null);
|
"NacosDataSource properties value not correct. serverAddr is empty but there is empty value in accessKey, secretKey, endpoint, namespace property");
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,30 +110,9 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties {
|
|||||||
this.secretKey = secretKey;
|
this.secretKey = secretKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NacosDataSourceProperties buildFlowByEDAS() {
|
public boolean acmPropertiesInvalid() {
|
||||||
return buildByEDAS("flow");
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
package org.springframework.cloud.alibaba.sentinel.datasource.config;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;
|
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,6 +32,7 @@ public class ZookeeperDataSourceProperties extends AbstractDataSourceProperties
|
|||||||
super(ZookeeperDataSourceFactoryBean.class.getName());
|
super(ZookeeperDataSourceFactoryBean.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private String serverAddr;
|
private String serverAddr;
|
||||||
|
|
||||||
private String path;
|
private String path;
|
||||||
|
@ -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;
|
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.authority.AuthorityRule;
|
||||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
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.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.block.flow.param.ParamFlowRule;
|
||||||
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
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.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,138 +35,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
* @see ParamFlowRule
|
* @see ParamFlowRule
|
||||||
* @see ObjectMapper
|
* @see ObjectMapper
|
||||||
*/
|
*/
|
||||||
public class JsonConverter implements Converter<String, List<AbstractRule>> {
|
public class JsonConverter<T> extends SentinelConverter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(JsonConverter.class);
|
public JsonConverter(ObjectMapper objectMapper, Class<T> ruleClass) {
|
||||||
|
super(objectMapper, ruleClass);
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
public JsonConverter(ObjectMapper objectMapper) {
|
|
||||||
this.objectMapper = objectMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AbstractRule> convert(String source) {
|
|
||||||
List<AbstractRule> 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<List<HashMap>>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
for (Object obj : jsonArray) {
|
|
||||||
String itemJson = null;
|
|
||||||
try {
|
|
||||||
itemJson = objectMapper.writeValueAsString(obj);
|
|
||||||
}
|
|
||||||
catch (JsonProcessingException e) {
|
|
||||||
// won't be happen
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AbstractRule> rules = Arrays.asList(convertFlowRule(itemJson),
|
|
||||||
convertDegradeRule(itemJson), convertSystemRule(itemJson),
|
|
||||||
convertAuthorityRule(itemJson), convertParamFlowRule(itemJson));
|
|
||||||
|
|
||||||
List<AbstractRule> 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||||
|
* @see FlowRule
|
||||||
|
* @see DegradeRule
|
||||||
|
* @see SystemRule
|
||||||
|
* @see AuthorityRule
|
||||||
|
* @see ParamFlowRule
|
||||||
|
* @see ObjectMapper
|
||||||
|
*/
|
||||||
|
public abstract class SentinelConverter<T extends AbstractRule>
|
||||||
|
implements Converter<String, List<AbstractRule>> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SentinelConverter.class);
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private final Class<T> ruleClass;
|
||||||
|
|
||||||
|
public SentinelConverter(ObjectMapper objectMapper, Class<T> ruleClass) {
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
this.ruleClass = ruleClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractRule> convert(String source) {
|
||||||
|
List<AbstractRule> 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<List<HashMap>>() {
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
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.authority.AuthorityRule;
|
||||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
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.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.block.flow.param.ParamFlowRule;
|
||||||
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,139 +34,12 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
|||||||
* @see SystemRule
|
* @see SystemRule
|
||||||
* @see AuthorityRule
|
* @see AuthorityRule
|
||||||
* @see ParamFlowRule
|
* @see ParamFlowRule
|
||||||
* @see XmlMapper
|
* @see ObjectMapper
|
||||||
*/
|
*/
|
||||||
public class XmlConverter implements Converter<String, List<AbstractRule>> {
|
public class XmlConverter<T> extends SentinelConverter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(XmlConverter.class);
|
public XmlConverter(XmlMapper xmlMapper, Class<T> ruleClass) {
|
||||||
|
super(xmlMapper, ruleClass);
|
||||||
private final XmlMapper xmlMapper;
|
|
||||||
|
|
||||||
public XmlConverter(XmlMapper xmlMapper) {
|
|
||||||
this.xmlMapper = xmlMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AbstractRule> convert(String source) {
|
|
||||||
List<AbstractRule> 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<List<HashMap>>() {
|
|
||||||
});
|
|
||||||
|
|
||||||
for (Object obj : xmlArray) {
|
|
||||||
String itemXml = null;
|
|
||||||
try {
|
|
||||||
itemXml = xmlMapper.writeValueAsString(obj);
|
|
||||||
}
|
|
||||||
catch (JsonProcessingException e) {
|
|
||||||
// won't be happen
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AbstractRule> rules = Arrays.asList(convertFlowRule(itemXml),
|
|
||||||
convertDegradeRule(itemXml), convertSystemRule(itemXml),
|
|
||||||
convertAuthorityRule(itemXml), convertParamFlowRule(itemXml));
|
|
||||||
|
|
||||||
List<AbstractRule> 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
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.Converter;
|
||||||
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
|
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
|
||||||
|
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link FactoryBean} for creating {@link NacosDataSource} instance.
|
* A {@link FactoryBean} for creating {@link NacosDataSource} instance.
|
||||||
@ -18,14 +38,26 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
|
|||||||
private String dataId;
|
private String dataId;
|
||||||
private Converter converter;
|
private Converter converter;
|
||||||
|
|
||||||
@Override
|
private String endpoint;
|
||||||
public NacosDataSource getObject() throws Exception {
|
private String namespace;
|
||||||
return new NacosDataSource(serverAddr, groupId, dataId, converter);
|
private String accessKey;
|
||||||
}
|
private String secretKey;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getObjectType() {
|
public NacosDataSource getObject() throws Exception {
|
||||||
return NacosDataSource.class;
|
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
|
@Override
|
||||||
@ -33,6 +65,11 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getObjectType() {
|
||||||
|
return NacosDataSource.class;
|
||||||
|
}
|
||||||
|
|
||||||
public String getServerAddr() {
|
public String getServerAddr() {
|
||||||
return serverAddr;
|
return serverAddr;
|
||||||
}
|
}
|
||||||
@ -64,4 +101,36 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
|
|||||||
public void setConverter(Converter converter) {
|
public void setConverter(Converter converter) {
|
||||||
this.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
|
||||||
* @see NacosDataSource
|
|
||||||
*/
|
|
||||||
public class NacosDataSourceWithAuthorizationFactoryBean
|
|
||||||
implements FactoryBean<NacosDataSourceWithAuthorization> {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,6 +52,12 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-commons</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.csp</groupId>
|
<groupId>com.alibaba.csp</groupId>
|
||||||
<artifactId>sentinel-parameter-flow-control</artifactId>
|
<artifactId>sentinel-parameter-flow-control</artifactId>
|
||||||
|
@ -23,7 +23,10 @@ public interface SentinelConstants {
|
|||||||
|
|
||||||
String PROPERTY_PREFIX = "spring.cloud.sentinel";
|
String PROPERTY_PREFIX = "spring.cloud.sentinel";
|
||||||
|
|
||||||
// commercialized
|
String BLOCK_TYPE = "block";
|
||||||
|
String FALLBACK_TYPE = "fallback";
|
||||||
|
|
||||||
|
// commercialization
|
||||||
|
|
||||||
String FLOW_DATASOURCE_NAME = "edas-flow";
|
String FLOW_DATASOURCE_NAME = "edas-flow";
|
||||||
String DEGRADE_DATASOURCE_NAME = "edas-degrade";
|
String DEGRADE_DATASOURCE_NAME = "edas-degrade";
|
||||||
|
@ -20,77 +20,76 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
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.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||||
import com.alibaba.csp.sentinel.log.LogBase;
|
import com.alibaba.csp.sentinel.log.LogBase;
|
||||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link ConfigurationProperties} for Sentinel.
|
||||||
|
*
|
||||||
* @author xiaojing
|
* @author xiaojing
|
||||||
* @author hengyunabc
|
* @author hengyunabc
|
||||||
* @author jiashuai.xie
|
* @author jiashuai.xie
|
||||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX)
|
@ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX)
|
||||||
|
@Validated
|
||||||
public class SentinelProperties {
|
public class SentinelProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* earlier initialize heart-beat when the spring container starts <note> when the
|
* Earlier initialize heart-beat when the spring container starts when the transport
|
||||||
* transport dependency is on classpath ,the configuration is effective </note>
|
* dependency is on classpath, the configuration is effective.
|
||||||
*/
|
*/
|
||||||
private boolean eager = false;
|
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;
|
private boolean enabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'
|
* Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'.
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private Map<String, DataSourcePropertiesConfiguration> datasource = new TreeMap<>(
|
private Map<String, DataSourcePropertiesConfiguration> datasource = new TreeMap<>(
|
||||||
String.CASE_INSENSITIVE_ORDER);
|
String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* transport configuration about dashboard and client
|
* Transport configuration about dashboard and client.
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Transport transport = new Transport();
|
private Transport transport = new Transport();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* metric configuration about resource
|
* Metric configuration about resource.
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Metric metric = new Metric();
|
private Metric metric = new Metric();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* web servlet configuration <note> when the application is web ,the configuration is
|
* Web servlet configuration when the application is web, the configuration is
|
||||||
* effective </note>
|
* effective.
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Servlet servlet = new Servlet();
|
private Servlet servlet = new Servlet();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sentinel filter <note> when the application is web ,the configuration is effective
|
* Sentinel filter when the application is web, the configuration is effective.
|
||||||
* </note>
|
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Filter filter = new Filter();
|
private Filter filter = new Filter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* flow configuration
|
* Sentinel Flow configuration.
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Flow flow = new Flow();
|
private Flow flow = new Flow();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sentinel log configuration {@link LogBase}
|
* Sentinel log configuration {@link LogBase}.
|
||||||
*/
|
*/
|
||||||
@NestedConfigurationProperty
|
|
||||||
private Log log = new Log();
|
private Log log = new Log();
|
||||||
|
|
||||||
public boolean isEager() {
|
public boolean isEager() {
|
||||||
@ -168,7 +167,7 @@ public class SentinelProperties {
|
|||||||
public static class Flow {
|
public static class Flow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the cold factor {@link SentinelConfig#COLD_FACTOR}
|
* The cold factor {@link SentinelConfig#COLD_FACTOR}.
|
||||||
*/
|
*/
|
||||||
private String coldFactor = "3";
|
private String coldFactor = "3";
|
||||||
|
|
||||||
@ -185,7 +184,7 @@ public class SentinelProperties {
|
|||||||
public static class Servlet {
|
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;
|
private String blockPage;
|
||||||
|
|
||||||
@ -201,17 +200,17 @@ public class SentinelProperties {
|
|||||||
public static class Metric {
|
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;
|
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;
|
private String fileTotalCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* charset when sentinel write or search metric file
|
* Charset when sentinel write or search metric file.
|
||||||
* {@link SentinelConfig#CHARSET}
|
* {@link SentinelConfig#CHARSET}
|
||||||
*/
|
*/
|
||||||
private String charset = "UTF-8";
|
private String charset = "UTF-8";
|
||||||
@ -244,22 +243,28 @@ public class SentinelProperties {
|
|||||||
public static class Transport {
|
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";
|
private String port = "8719";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sentinel dashboard address, won't try to connect dashboard when address is
|
* Sentinel dashboard address, won't try to connect dashboard when address is
|
||||||
* empty {@link TransportConfig#CONSOLE_SERVER}
|
* empty {@link TransportConfig#CONSOLE_SERVER}.
|
||||||
*/
|
*/
|
||||||
private String dashboard = "";
|
private String dashboard = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send heartbeat interval millisecond
|
* Send heartbeat interval millisecond
|
||||||
* {@link TransportConfig#HEARTBEAT_INTERVAL_MS}
|
* {@link TransportConfig#HEARTBEAT_INTERVAL_MS}.
|
||||||
*/
|
*/
|
||||||
private String heartbeatIntervalMs;
|
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() {
|
public String getHeartbeatIntervalMs() {
|
||||||
return heartbeatIntervalMs;
|
return heartbeatIntervalMs;
|
||||||
}
|
}
|
||||||
@ -284,12 +289,19 @@ public class SentinelProperties {
|
|||||||
this.dashboard = dashboard;
|
this.dashboard = dashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientIp() {
|
||||||
|
return clientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientIp(String clientIp) {
|
||||||
|
this.clientIp = clientIp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Filter {
|
public static class Filter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sentinel filter chain order.
|
* Sentinel filter chain order.
|
||||||
*/
|
*/
|
||||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||||
|
|
||||||
@ -318,12 +330,12 @@ public class SentinelProperties {
|
|||||||
public static class Log {
|
public static class Log {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sentinel log base dir
|
* Sentinel log base dir.
|
||||||
*/
|
*/
|
||||||
private String dir;
|
private String dir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* distinguish the log file by pid number
|
* Distinguish the log file by pid number.
|
||||||
*/
|
*/
|
||||||
private boolean switchPid = false;
|
private boolean switchPid = false;
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaojing
|
* @author xiaojing
|
||||||
*/
|
*/
|
||||||
@ -54,11 +54,6 @@ public class SentinelWebAutoConfiguration {
|
|||||||
|
|
||||||
SentinelProperties.Filter filterConfig = properties.getFilter();
|
SentinelProperties.Filter filterConfig = properties.getFilter();
|
||||||
|
|
||||||
if (null == filterConfig) {
|
|
||||||
filterConfig = new SentinelProperties.Filter();
|
|
||||||
properties.setFilter(filterConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterConfig.getUrlPatterns() == null
|
if (filterConfig.getUrlPatterns() == null
|
||||||
|| filterConfig.getUrlPatterns().isEmpty()) {
|
|| filterConfig.getUrlPatterns().isEmpty()) {
|
||||||
List<String> defaultPatterns = new ArrayList<>();
|
List<String> defaultPatterns = new ArrayList<>();
|
||||||
|
@ -20,6 +20,7 @@ import javax.annotation.PostConstruct;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
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.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
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.SentinelProperties;
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter;
|
import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter;
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.util.StringUtils;
|
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.UrlBlockHandler;
|
||||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
|
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
|
||||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
|
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.config.SentinelConfig;
|
||||||
import com.alibaba.csp.sentinel.init.InitExecutor;
|
import com.alibaba.csp.sentinel.init.InitExecutor;
|
||||||
import com.alibaba.csp.sentinel.log.LogBase;
|
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.transport.config.TransportConfig;
|
||||||
import com.alibaba.csp.sentinel.util.AppNameUtil;
|
import com.alibaba.csp.sentinel.util.AppNameUtil;
|
||||||
|
|
||||||
@ -47,6 +55,7 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaojing
|
* @author xiaojing
|
||||||
|
* @author jiashuai.xie
|
||||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ -66,8 +75,20 @@ public class SentinelAutoConfiguration {
|
|||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private UrlBlockHandler urlBlockHandler;
|
private UrlBlockHandler urlBlockHandler;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private RequestOriginParser requestOriginParser;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void init() {
|
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))
|
if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME))
|
||||||
&& StringUtils.hasText(projectName)) {
|
&& StringUtils.hasText(projectName)) {
|
||||||
System.setProperty(AppNameUtil.APP_NAME, projectName);
|
System.setProperty(AppNameUtil.APP_NAME, projectName);
|
||||||
@ -88,6 +109,11 @@ public class SentinelAutoConfiguration {
|
|||||||
System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS,
|
System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS,
|
||||||
properties.getTransport().getHeartbeatIntervalMs());
|
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))
|
if (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET))
|
||||||
&& StringUtils.hasText(properties.getMetric().getCharset())) {
|
&& StringUtils.hasText(properties.getMetric().getCharset())) {
|
||||||
System.setProperty(SentinelConfig.CHARSET,
|
System.setProperty(SentinelConfig.CHARSET,
|
||||||
@ -110,30 +136,25 @@ public class SentinelAutoConfiguration {
|
|||||||
System.setProperty(SentinelConfig.COLD_FACTOR,
|
System.setProperty(SentinelConfig.COLD_FACTOR,
|
||||||
properties.getFlow().getColdFactor());
|
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())) {
|
if (StringUtils.hasText(properties.getServlet().getBlockPage())) {
|
||||||
WebServletConfig.setBlockPage(properties.getServlet().getBlockPage());
|
WebServletConfig.setBlockPage(properties.getServlet().getBlockPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urlBlockHandler != null) {
|
if (urlBlockHandler != null) {
|
||||||
WebCallbackManager.setUrlBlockHandler(urlBlockHandler);
|
WebCallbackManager.setUrlBlockHandler(urlBlockHandler);
|
||||||
}
|
}
|
||||||
if (urlCleaner != null) {
|
if (urlCleaner != null) {
|
||||||
WebCallbackManager.setUrlCleaner(urlCleaner);
|
WebCallbackManager.setUrlCleaner(urlCleaner);
|
||||||
}
|
}
|
||||||
|
if (requestOriginParser != null) {
|
||||||
|
WebCallbackManager.setRequestOriginParser(requestOriginParser);
|
||||||
|
}
|
||||||
|
|
||||||
// earlier initialize
|
// earlier initialize
|
||||||
if (properties.isEager()) {
|
if (properties.isEager()) {
|
||||||
InitExecutor.doInit();
|
InitExecutor.doInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -145,34 +166,78 @@ public class SentinelAutoConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||||
public SentinelBeanPostProcessor sentinelBeanPostProcessor() {
|
public SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||||
return new SentinelBeanPostProcessor();
|
ApplicationContext applicationContext) {
|
||||||
|
return new SentinelBeanPostProcessor(applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SentinelDataSourceHandler sentinelDataSourceHandler() {
|
public SentinelDataSourceHandler sentinelDataSourceHandler(
|
||||||
return new SentinelDataSourceHandler();
|
DefaultListableBeanFactory beanFactory) {
|
||||||
|
return new SentinelDataSourceHandler(beanFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean("sentinel-json-converter")
|
protected static class SentinelConverterConfiguration {
|
||||||
public JsonConverter jsonConverter() {
|
|
||||||
return new JsonConverter(objectMapper());
|
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)
|
@ConditionalOnClass(XmlMapper.class)
|
||||||
protected static class SentinelXmlConfiguration {
|
protected static class SentinelXmlConfiguration {
|
||||||
@Bean("sentinel-xml-converter")
|
|
||||||
public XmlConverter xmlConverter() {
|
private XmlMapper xmlMapper = new XmlMapper();
|
||||||
return new XmlConverter(xmlMapper());
|
|
||||||
|
@Bean("sentinel-xml-flow-converter")
|
||||||
|
public XmlConverter xmlFlowConverter() {
|
||||||
|
return new XmlConverter(xmlMapper, FlowRule.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private XmlMapper xmlMapper() {
|
@Bean("sentinel-xml-degrade-converter")
|
||||||
return new XmlMapper();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,34 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
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 java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
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.cloud.alibaba.sentinel.annotation.SentinelRestTemplate;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.type.StandardMethodMetadata;
|
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.util.StringUtils;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for RestTemplate
|
* PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for RestTemplate
|
||||||
*
|
*
|
||||||
@ -40,8 +53,14 @@ import org.springframework.web.client.RestTemplate;
|
|||||||
*/
|
*/
|
||||||
public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
|
public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
|
||||||
|
|
||||||
@Autowired
|
private static final Logger logger = LoggerFactory
|
||||||
private ApplicationContext applicationContext;
|
.getLogger(SentinelBeanPostProcessor.class);
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public SentinelBeanPostProcessor(ApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
private ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@ -49,21 +68,113 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
|
|||||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
|
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
|
||||||
Class<?> beanType, String beanName) {
|
Class<?> beanType, String beanName) {
|
||||||
if (checkSentinelProtect(beanDefinition, beanType)) {
|
if (checkSentinelProtect(beanDefinition, beanType)) {
|
||||||
SentinelRestTemplate sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition
|
SentinelRestTemplate sentinelRestTemplate;
|
||||||
|
if (beanDefinition.getSource() instanceof StandardMethodMetadata) {
|
||||||
|
sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition
|
||||||
.getSource()).getIntrospectedMethod()
|
.getSource()).getIntrospectedMethod()
|
||||||
.getAnnotation(SentinelRestTemplate.class);
|
.getAnnotation(SentinelRestTemplate.class);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sentinelRestTemplate = beanDefinition.getResolvedFactoryMethod()
|
||||||
|
.getAnnotation(SentinelRestTemplate.class);
|
||||||
|
}
|
||||||
|
// check class and method validation
|
||||||
|
checkSentinelRestTemplate(sentinelRestTemplate, beanName);
|
||||||
cache.put(beanName, sentinelRestTemplate);
|
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<String> 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,
|
private boolean checkSentinelProtect(RootBeanDefinition beanDefinition,
|
||||||
Class<?> beanType) {
|
Class<?> beanType) {
|
||||||
return beanType == RestTemplate.class
|
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())
|
&& ((StandardMethodMetadata) beanDefinition.getSource())
|
||||||
.isAnnotated(SentinelRestTemplate.class.getName());
|
.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
|
@Override
|
||||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
@ -84,7 +195,7 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
|
|||||||
SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext
|
SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext
|
||||||
.getBean(interceptorBeanName.toString(),
|
.getBean(interceptorBeanName.toString(),
|
||||||
SentinelProtectInterceptor.class);
|
SentinelProtectInterceptor.class);
|
||||||
restTemplate.getInterceptors().add(sentinelProtectInterceptor);
|
restTemplate.getInterceptors().add(0, sentinelProtectInterceptor);
|
||||||
}
|
}
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
@ -103,10 +214,4 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
|
|||||||
interceptorBeanDefinition);
|
interceptorBeanDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
|
||||||
throws BeansException {
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
* <p>
|
||||||
|
* support @EnableCircuitBreaker ,Do nothing
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SentinelCircuitBreakerConfiguration {
|
||||||
|
}
|
@ -17,47 +17,29 @@
|
|||||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
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.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.AbstractDataSourceProperties;
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration;
|
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.JsonConverter;
|
||||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
|
import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
|
||||||
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
|
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.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
|
* Sentinel {@link ReadableDataSource} Handler Handle the configurations of
|
||||||
@ -68,59 +50,32 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
|
|||||||
* @see JsonConverter
|
* @see JsonConverter
|
||||||
* @see XmlConverter
|
* @see XmlConverter
|
||||||
*/
|
*/
|
||||||
public class SentinelDataSourceHandler {
|
public class SentinelDataSourceHandler implements SmartInitializingSingleton {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
private static final Logger logger = LoggerFactory
|
||||||
.getLogger(SentinelDataSourceHandler.class);
|
.getLogger(SentinelDataSourceHandler.class);
|
||||||
|
|
||||||
private List<String> dataTypeList = Arrays.asList("json", "xml");
|
private List<String> dataTypeList = Arrays.asList("json", "xml");
|
||||||
|
|
||||||
private List<Class<? extends AbstractRule>> rulesList = Arrays.asList(FlowRule.class,
|
private final String DATA_TYPE_FIELD = "dataType";
|
||||||
DegradeRule.class, SystemRule.class, AuthorityRule.class,
|
private final String CUSTOM_DATA_TYPE = "custom";
|
||||||
ParamFlowRule.class);
|
private final String CONVERTER_CLASS_FIELD = "converterClass";
|
||||||
|
|
||||||
private List<String> dataSourceBeanNameList = Collections
|
private final DefaultListableBeanFactory beanFactory;
|
||||||
.synchronizedList(new ArrayList<String>());
|
|
||||||
|
|
||||||
private final String DATATYPE_FIELD = "dataType";
|
public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory) {
|
||||||
private final String CUSTOM_DATATYPE = "custom";
|
this.beanFactory = beanFactory;
|
||||||
private final String CONVERTERCLASS_FIELD = "converterClass";
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SentinelProperties sentinelProperties;
|
private SentinelProperties sentinelProperties;
|
||||||
|
|
||||||
@EventListener(classes = ApplicationReadyEvent.class)
|
@Override
|
||||||
public void buildDataSource(ApplicationReadyEvent event) throws Exception {
|
public void afterSingletonsInstantiated() {
|
||||||
|
for (String dataSourceName : sentinelProperties.getDatasource().keySet()) {
|
||||||
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) event
|
DataSourcePropertiesConfiguration dataSourceProperties = sentinelProperties
|
||||||
.getApplicationContext().getAutowireCapableBeanFactory();
|
.getDatasource().get(dataSourceName);
|
||||||
|
try {
|
||||||
// commercialization
|
|
||||||
if (!StringUtils.isEmpty(System.getProperties()
|
|
||||||
.getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) {
|
|
||||||
Map<String, DataSourcePropertiesConfiguration> newDataSourceMap = new TreeMap<>(
|
|
||||||
String.CASE_INSENSITIVE_ORDER);
|
|
||||||
for (Map.Entry<String, DataSourcePropertiesConfiguration> 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<String, DataSourcePropertiesConfiguration> entry : sentinelProperties
|
|
||||||
.getDatasource().entrySet()) {
|
|
||||||
String dataSourceName = entry.getKey();
|
|
||||||
DataSourcePropertiesConfiguration dataSourceProperties = entry.getValue();
|
|
||||||
|
|
||||||
List<String> validFields = dataSourceProperties.getValidField();
|
List<String> validFields = dataSourceProperties.getValidField();
|
||||||
if (validFields.size() != 1) {
|
if (validFields.size() != 1) {
|
||||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||||
@ -128,53 +83,20 @@ public class SentinelDataSourceHandler {
|
|||||||
+ dataSourceProperties.getValidField());
|
+ dataSourceProperties.getValidField());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties
|
AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties
|
||||||
.getValidDataSourceProperties();
|
.getValidDataSourceProperties();
|
||||||
abstractDataSourceProperties.preCheck();
|
abstractDataSourceProperties.preCheck(dataSourceName);
|
||||||
registerBean(beanFactory, abstractDataSourceProperties,
|
registerBean(abstractDataSourceProperties, dataSourceName + "-sentinel-"
|
||||||
dataSourceName + "-sentinel-" + validFields.get(0) + "-datasource");
|
+ validFields.get(0) + "-datasource");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String beanName : dataSourceBeanNameList) {
|
|
||||||
ReadableDataSource dataSource = beanFactory.getBean(beanName,
|
|
||||||
ReadableDataSource.class);
|
|
||||||
Object ruleConfig;
|
|
||||||
try {
|
|
||||||
logger.info("[Sentinel Starter] DataSource " + beanName
|
|
||||||
+ " start to loadConfig");
|
|
||||||
ruleConfig = dataSource.loadConfig();
|
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
logger.error("[Sentinel Starter] DataSource " + beanName
|
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||||
+ " loadConfig error: " + e.getMessage(), e);
|
+ " build error: " + e.getMessage(), e);
|
||||||
return;
|
|
||||||
}
|
|
||||||
SentinelProperty sentinelProperty = dataSource.getProperty();
|
|
||||||
Class ruleType = getAndCheckRuleType(ruleConfig, beanName);
|
|
||||||
if (ruleType != null) {
|
|
||||||
if (ruleType == FlowRule.class) {
|
|
||||||
FlowRuleManager.register2Property(sentinelProperty);
|
|
||||||
}
|
|
||||||
else if (ruleType == DegradeRule.class) {
|
|
||||||
DegradeRuleManager.register2Property(sentinelProperty);
|
|
||||||
}
|
|
||||||
else if (ruleType == SystemRule.class) {
|
|
||||||
SystemRuleManager.register2Property(sentinelProperty);
|
|
||||||
}
|
|
||||||
else if (ruleType == AuthorityRule.class) {
|
|
||||||
AuthorityRuleManager.register2Property(sentinelProperty);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ParamFlowRuleManager.register2Property(sentinelProperty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerBean(DefaultListableBeanFactory beanFactory,
|
private void registerBean(final AbstractDataSourceProperties dataSourceProperties,
|
||||||
final AbstractDataSourceProperties dataSourceProperties,
|
|
||||||
String dataSourceName) {
|
String dataSourceName) {
|
||||||
|
|
||||||
Map<String, Object> propertyMap = new HashMap<>();
|
Map<String, Object> propertyMap = new HashMap<>();
|
||||||
@ -194,8 +116,9 @@ public class SentinelDataSourceHandler {
|
|||||||
e);
|
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
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||||
.genericBeanDefinition(dataSourceProperties.getFactoryBeanName());
|
.genericBeanDefinition(dataSourceProperties.getFactoryBeanName());
|
||||||
@ -205,16 +128,17 @@ public class SentinelDataSourceHandler {
|
|||||||
Object propertyValue = entry.getValue();
|
Object propertyValue = entry.getValue();
|
||||||
Field field = ReflectionUtils.findField(dataSourceProperties.getClass(),
|
Field field = ReflectionUtils.findField(dataSourceProperties.getClass(),
|
||||||
propertyName);
|
propertyName);
|
||||||
if (field != null) {
|
if (null == field) {
|
||||||
if (DATATYPE_FIELD.equals(propertyName)) {
|
continue;
|
||||||
String dataType = StringUtils
|
}
|
||||||
.trimAllWhitespace(propertyValue.toString());
|
if (DATA_TYPE_FIELD.equals(propertyName)) {
|
||||||
if (CUSTOM_DATATYPE.equals(dataType)) {
|
String dataType = StringUtils.trimAllWhitespace(propertyValue.toString());
|
||||||
|
if (CUSTOM_DATA_TYPE.equals(dataType)) {
|
||||||
try {
|
try {
|
||||||
if (StringUtils
|
if (StringUtils
|
||||||
.isEmpty(dataSourceProperties.getConverterClass())) {
|
.isEmpty(dataSourceProperties.getConverterClass())) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||||
"[Sentinel Starter] DataSource " + dataSourceName
|
+ dataSourceName
|
||||||
+ "dataType is custom, please set converter-class "
|
+ "dataType is custom, please set converter-class "
|
||||||
+ "property");
|
+ "property");
|
||||||
}
|
}
|
||||||
@ -222,16 +146,15 @@ public class SentinelDataSourceHandler {
|
|||||||
// configuration and register
|
// configuration and register
|
||||||
String customConvertBeanName = "sentinel-"
|
String customConvertBeanName = "sentinel-"
|
||||||
+ dataSourceProperties.getConverterClass();
|
+ dataSourceProperties.getConverterClass();
|
||||||
if (!beanFactory.containsBean(customConvertBeanName)) {
|
if (!this.beanFactory.containsBean(customConvertBeanName)) {
|
||||||
beanFactory.registerBeanDefinition(customConvertBeanName,
|
this.beanFactory.registerBeanDefinition(customConvertBeanName,
|
||||||
BeanDefinitionBuilder
|
BeanDefinitionBuilder
|
||||||
.genericBeanDefinition(
|
.genericBeanDefinition(
|
||||||
Class.forName(dataSourceProperties
|
Class.forName(dataSourceProperties
|
||||||
.getConverterClass()))
|
.getConverterClass()))
|
||||||
.getBeanDefinition());
|
.getBeanDefinition());
|
||||||
}
|
}
|
||||||
builder.addPropertyReference("converter",
|
builder.addPropertyReference("converter", customConvertBeanName);
|
||||||
customConvertBeanName);
|
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e) {
|
catch (ClassNotFoundException e) {
|
||||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||||
@ -239,19 +162,16 @@ public class SentinelDataSourceHandler {
|
|||||||
+ dataSourceProperties.getClass().getSimpleName()
|
+ dataSourceProperties.getClass().getSimpleName()
|
||||||
+ " error, class name: "
|
+ " error, class name: "
|
||||||
+ dataSourceProperties.getConverterClass());
|
+ dataSourceProperties.getConverterClass());
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||||
"[Sentinel Starter] DataSource " + dataSourceName
|
+ dataSourceName + " handle "
|
||||||
+ " handle "
|
+ dataSourceProperties.getClass().getSimpleName()
|
||||||
+ dataSourceProperties.getClass()
|
|
||||||
.getSimpleName()
|
|
||||||
+ " error, class name: "
|
+ " error, class name: "
|
||||||
+ dataSourceProperties.getConverterClass(),
|
+ dataSourceProperties.getConverterClass(), e);
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!dataTypeList.contains(StringUtils
|
if (!dataTypeList.contains(
|
||||||
.trimAllWhitespace(propertyValue.toString()))) {
|
StringUtils.trimAllWhitespace(propertyValue.toString()))) {
|
||||||
throw new RuntimeException("[Sentinel Starter] DataSource "
|
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||||
+ dataSourceName + " dataType: " + propertyValue
|
+ dataSourceName + " dataType: " + propertyValue
|
||||||
+ " is not support now. please using these types: "
|
+ " is not support now. please using these types: "
|
||||||
@ -259,12 +179,14 @@ public class SentinelDataSourceHandler {
|
|||||||
}
|
}
|
||||||
// converter type now support xml or json.
|
// converter type now support xml or json.
|
||||||
// The bean name of these converters wrapped by
|
// The bean name of these converters wrapped by
|
||||||
// 'sentinel-{converterType}-converter'
|
// 'sentinel-{converterType}-{ruleType}-converter'
|
||||||
builder.addPropertyReference("converter",
|
builder.addPropertyReference("converter",
|
||||||
"sentinel-" + propertyValue.toString() + "-converter");
|
"sentinel-" + propertyValue.toString() + "-"
|
||||||
|
+ dataSourceProperties.getRuleType().getName()
|
||||||
|
+ "-converter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CONVERTERCLASS_FIELD.equals(propertyName)) {
|
else if (CONVERTER_CLASS_FIELD.equals(propertyName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -274,97 +196,68 @@ public class SentinelDataSourceHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
beanFactory.registerBeanDefinition(dataSourceName, builder.getBeanDefinition());
|
this.beanFactory.registerBeanDefinition(dataSourceName,
|
||||||
|
builder.getBeanDefinition());
|
||||||
// init in Spring
|
// init in Spring
|
||||||
AbstractDataSource newDataSource = (AbstractDataSource) beanFactory
|
AbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory
|
||||||
.getBean(dataSourceName);
|
.getBean(dataSourceName);
|
||||||
// commercialization
|
|
||||||
if (!StringUtils.isEmpty(System.getProperties()
|
logAndCheckRuleType(newDataSource, dataSourceName,
|
||||||
.getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) {
|
dataSourceProperties.getRuleType().getClazz());
|
||||||
if (dataSourceName.contains(SentinelConstants.FLOW_DATASOURCE_NAME)) {
|
|
||||||
FlowRuleManager.register2Property(newDataSource.getProperty());
|
// register property in RuleManager
|
||||||
}
|
dataSourceProperties.postRegister(newDataSource);
|
||||||
else if (dataSourceName.contains(SentinelConstants.DEGRADE_DATASOURCE_NAME)) {
|
|
||||||
DegradeRuleManager.register2Property(newDataSource.getProperty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataSourceBeanNameList.add(dataSourceName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class getAndCheckRuleType(Object ruleConfig, String dataSourceName) {
|
private void logAndCheckRuleType(AbstractDataSource dataSource, String dataSourceName,
|
||||||
if (rulesList.contains(ruleConfig.getClass())) {
|
Class<? extends AbstractRule> ruleClass) {
|
||||||
logger.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName, 1,
|
Object ruleConfig;
|
||||||
ruleConfig.getClass().getSimpleName());
|
try {
|
||||||
return ruleConfig.getClass();
|
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;
|
List convertedRuleList = (List) ruleConfig;
|
||||||
if (CollectionUtils.isEmpty(convertedRuleList)) {
|
if (CollectionUtils.isEmpty(convertedRuleList)) {
|
||||||
logger.warn("[Sentinel Starter] DataSource {} rule list is empty.",
|
logger.warn("[Sentinel Starter] DataSource {} rule list is empty.",
|
||||||
dataSourceName);
|
dataSourceName);
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
int matchCount = 0;
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<Class> classList = new ArrayList<>();
|
|
||||||
for (Object rule : convertedRuleList) {
|
for (Object rule : convertedRuleList) {
|
||||||
classList.add(rule.getClass());
|
if (rule.getClass() == ruleClass) {
|
||||||
|
matchCount++;
|
||||||
}
|
}
|
||||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
}
|
||||||
+ " rule class is invalid. Class List: " + classList);
|
if (matchCount == 0) {
|
||||||
throw new RuntimeException(
|
logger.error("[Sentinel Starter] DataSource {} none rules are {} type.",
|
||||||
"[Sentinel Starter] DataSource " + dataSourceName
|
dataSourceName, ruleClass.getSimpleName());
|
||||||
+ " rule class is invalid. Class List: " + classList);
|
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 {
|
||||||
|
logger.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName,
|
||||||
|
convertedRuleList.size(), ruleClass.getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||||
+ " rule class is invalid. Class: " + ruleConfig.getClass());
|
+ " rule class is not List<" + ruleClass.getSimpleName()
|
||||||
throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName
|
+ ">. Class: " + ruleConfig.getClass());
|
||||||
+ " rule class is invalid. 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<String> getDataSourceBeanNameList() {
|
|
||||||
return dataSourceBeanNameList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -29,7 +29,6 @@ import org.springframework.http.HttpRequest;
|
|||||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||||
import org.springframework.http.client.ClientHttpResponse;
|
import org.springframework.http.client.ClientHttpResponse;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.Entry;
|
import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.SphU;
|
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.context.ContextUtil;
|
||||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
|
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
|
||||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interceptor using by SentinelRestTemplate
|
* Interceptor using by SentinelRestTemplate
|
||||||
*
|
*
|
||||||
* @author fangjian
|
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||||
*/
|
*/
|
||||||
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
|
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
private static final Logger logger = LoggerFactory
|
||||||
.getLogger(SentinelProtectInterceptor.class);
|
.getLogger(SentinelProtectInterceptor.class);
|
||||||
|
|
||||||
private SentinelRestTemplate sentinelRestTemplate;
|
private final SentinelRestTemplate sentinelRestTemplate;
|
||||||
|
|
||||||
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) {
|
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) {
|
||||||
this.sentinelRestTemplate = sentinelRestTemplate;
|
this.sentinelRestTemplate = sentinelRestTemplate;
|
||||||
@ -82,18 +80,7 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
|
|||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
return handleBlockException(request, body, execution, (BlockException) e);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@ -109,84 +96,49 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ClientHttpResponse handleBlockException(HttpRequest request, byte[] body,
|
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 };
|
Object[] args = new Object[] { request, body, execution, ex };
|
||||||
// handle degrade
|
// handle degrade
|
||||||
if (isDegradeFailure(ex)) {
|
if (isDegradeFailure(ex)) {
|
||||||
Method method = extractFallbackMethod(sentinelRestTemplate.fallback(),
|
Method fallbackMethod = extractFallbackMethod(sentinelRestTemplate.fallback(),
|
||||||
sentinelRestTemplate.fallbackClass());
|
sentinelRestTemplate.fallbackClass());
|
||||||
if (method != null) {
|
if (fallbackMethod != null) {
|
||||||
return (ClientHttpResponse) method.invoke(null, args);
|
return methodInvoke(fallbackMethod, args);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new SentinelClientHttpResponse();
|
return new SentinelClientHttpResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// handle block
|
// handle flow
|
||||||
Method blockHandler = extractBlockHandlerMethod(
|
Method blockHandler = extractBlockHandlerMethod(
|
||||||
sentinelRestTemplate.blockHandler(),
|
sentinelRestTemplate.blockHandler(),
|
||||||
sentinelRestTemplate.blockHandlerClass());
|
sentinelRestTemplate.blockHandlerClass());
|
||||||
if (blockHandler != null) {
|
if (blockHandler != null) {
|
||||||
return (ClientHttpResponse) blockHandler.invoke(null, args);
|
return methodInvoke(blockHandler, args);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new SentinelClientHttpResponse();
|
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) {
|
private Method extractFallbackMethod(String fallback, Class<?> fallbackClass) {
|
||||||
if (StringUtil.isBlank(fallback) || fallbackClass == void.class) {
|
return BlockClassRegistry.lookupFallback(fallbackClass, fallback);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method extractBlockHandlerMethod(String block, Class<?> blockClass) {
|
private Method extractBlockHandlerMethod(String block, Class<?> blockClass) {
|
||||||
if (StringUtil.isBlank(block) || blockClass == void.class) {
|
return BlockClassRegistry.lookupBlockHandler(blockClass, block);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDegradeFailure(BlockException ex) {
|
private boolean isDegradeFailure(BlockException ex) {
|
||||||
|
@ -17,24 +17,20 @@
|
|||||||
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||||
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
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.adapter.servlet.config.WebServletConfig;
|
||||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
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.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.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.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.slots.system.SystemRuleManager;
|
||||||
|
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint for Sentinel, contains ans properties and rules
|
* 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<Map<String, Object>> {
|
public class SentinelEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||||
|
|
||||||
@Autowired
|
private final SentinelProperties sentinelProperties;
|
||||||
private SentinelProperties sentinelProperties;
|
|
||||||
|
|
||||||
@Autowired
|
public SentinelEndpoint(SentinelProperties sentinelProperties) {
|
||||||
private SentinelDataSourceHandler dataSourceHandler;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
public SentinelEndpoint() {
|
|
||||||
super("sentinel");
|
super("sentinel");
|
||||||
|
this.sentinelProperties = sentinelProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> invoke() {
|
public Map<String, Object> invoke() {
|
||||||
Map<String, Object> result = new HashMap<>();
|
final Map<String, Object> result = new HashMap<>();
|
||||||
|
if (sentinelProperties.isEnabled()) {
|
||||||
|
|
||||||
List<FlowRule> flowRules = FlowRuleManager.getRules();
|
result.put("logDir", LogBase.getLogBaseDir());
|
||||||
List<DegradeRule> degradeRules = DegradeRuleManager.getRules();
|
result.put("logUsePid", LogBase.isLogNameUsePid());
|
||||||
List<SystemRule> systemRules = SystemRuleManager.getRules();
|
result.put("blockPage", WebServletConfig.getBlockPage());
|
||||||
List<ParamFlowRule> paramFlowRules = ParamFlowRuleManager.getRules();
|
result.put("metricsFileSize", SentinelConfig.singleMetricFileSize());
|
||||||
result.put("properties", sentinelProperties);
|
result.put("metricsFileCharset", SentinelConfig.charset());
|
||||||
result.put("FlowRules", flowRules);
|
result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount());
|
||||||
result.put("DegradeRules", degradeRules);
|
result.put("consoleServer", TransportConfig.getConsoleServer());
|
||||||
result.put("SystemRules", systemRules);
|
result.put("clientIp", TransportConfig.getHeartbeatClientIp());
|
||||||
result.put("ParamFlowRule", paramFlowRules);
|
result.put("heartbeatIntervalMs", TransportConfig.getHeartbeatIntervalMs());
|
||||||
result.put("datasources", new HashMap<String, Object>());
|
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()) {
|
final Map<String, Object> rules = new HashMap<>();
|
||||||
ReadableDataSource dataSource = applicationContext.getBean(dataSourceBeanName,
|
result.put("rules", rules);
|
||||||
ReadableDataSource.class);
|
rules.put("flowRules", FlowRuleManager.getRules());
|
||||||
try {
|
rules.put("degradeRules", DegradeRuleManager.getRules());
|
||||||
((HashMap) result.get("datasources")).put(dataSourceBeanName,
|
rules.put("systemRules", SystemRuleManager.getRules());
|
||||||
dataSource.loadConfig());
|
rules.put("authorityRule", AuthorityRuleManager.getRules());
|
||||||
}
|
rules.put("paramFlowRule", ParamFlowRuleManager.getRules());
|
||||||
catch (Exception e) {
|
|
||||||
((HashMap) result.get("datasources")).put(dataSourceBeanName,
|
|
||||||
"load error: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ public class SentinelEndpointAutoConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnEnabledEndpoint("sentinel")
|
@ConditionalOnEnabledEndpoint("sentinel")
|
||||||
public SentinelEndpoint sentinelEndPoint() {
|
public SentinelEndpoint sentinelEndPoint(SentinelProperties sentinelProperties) {
|
||||||
return new SentinelEndpoint();
|
return new SentinelEndpoint(sentinelProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.sentinel.rest;
|
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.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -31,6 +24,13 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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}
|
* Using by {@link SentinelRestTemplate} and {@link SentinelProtectInterceptor}
|
||||||
*
|
*
|
||||||
@ -41,7 +41,6 @@ public class SentinelClientHttpResponse extends AbstractClientHttpResponse {
|
|||||||
private String blockResponse = "RestTemplate request block by sentinel";
|
private String blockResponse = "RestTemplate request block by sentinel";
|
||||||
|
|
||||||
public SentinelClientHttpResponse() {
|
public SentinelClientHttpResponse() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SentinelClientHttpResponse(String blockResponse) {
|
public SentinelClientHttpResponse(String blockResponse) {
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
"defaultValue": "8719",
|
"defaultValue": "8719",
|
||||||
"description": "sentinel api port."
|
"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",
|
"name": "spring.cloud.sentinel.transport.dashboard",
|
||||||
"type": "java.lang.String",
|
"type": "java.lang.String",
|
||||||
|
@ -3,3 +3,6 @@ org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\
|
|||||||
org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
|
org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\
|
org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\
|
||||||
org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration
|
org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration
|
||||||
|
|
||||||
|
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
|
||||||
|
org.springframework.cloud.alibaba.sentinel.custom.SentinelCircuitBreakerConfiguration
|
@ -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.SentinelAutoConfiguration;
|
||||||
import org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor;
|
import org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor;
|
||||||
import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.client.RestTemplate;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
@ -109,8 +113,9 @@ public class SentinelAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class ExceptionUtil {
|
static class ExceptionUtil {
|
||||||
public static void handleException(BlockException ex) {
|
public static ClientHttpResponse handleException(HttpRequest request, byte[] body,
|
||||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
ClientHttpRequestExecution execution, BlockException ex) {
|
||||||
|
return new SentinelClientHttpResponse("custom block info");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
|
||||||
*/
|
|
||||||
public class SentinelAliCloudListener
|
|
||||||
extends AbstractOnceApplicationListener<ApplicationEnvironmentPreparedEvent> {
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -11,5 +11,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
|||||||
org.springframework.context.ApplicationListener=\
|
org.springframework.context.ApplicationListener=\
|
||||||
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\
|
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\
|
||||||
org.springframework.cloud.alicloud.context.nacos.NacosConfigParameterInitListener,\
|
org.springframework.cloud.alicloud.context.nacos.NacosConfigParameterInitListener,\
|
||||||
org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener,\
|
org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener
|
||||||
org.springframework.cloud.alicloud.context.sentinel.SentinelAliCloudListener
|
|
@ -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");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user