mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge remote-tracking branch 'upstream/master'
# Conflicts: # pom.xml # spring-cloud-alibaba-dependencies/pom.xml # spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml
This commit is contained in:
@@ -23,6 +23,9 @@ public interface SentinelConstants {
|
||||
|
||||
String PROPERTY_PREFIX = "spring.cloud.sentinel";
|
||||
|
||||
String BLOCK_TYPE = "block";
|
||||
String FALLBACK_TYPE = "fallback";
|
||||
|
||||
// commercialization
|
||||
|
||||
String FLOW_DATASOURCE_NAME = "edas-flow";
|
||||
|
@@ -16,21 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.log.LogBase;
|
||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.log.LogBase;
|
||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* {@link ConfigurationProperties} for Sentinel.
|
||||
*
|
||||
* @author xiaojing
|
||||
* @author hengyunabc
|
||||
* @author jiashuai.xie
|
||||
@@ -41,58 +41,51 @@ import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
public class SentinelProperties {
|
||||
|
||||
/**
|
||||
* earlier initialize heart-beat when the spring container starts <note> when the
|
||||
* transport dependency is on classpath ,the configuration is effective </note>
|
||||
* Earlier initialize heart-beat when the spring container starts when the transport
|
||||
* dependency is on classpath, the configuration is effective.
|
||||
*/
|
||||
private boolean eager = false;
|
||||
|
||||
/**
|
||||
* enable sentinel auto configure, the default value is true
|
||||
* Enable sentinel auto configure, the default value is true.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'
|
||||
* Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'.
|
||||
*/
|
||||
private Map<String, DataSourcePropertiesConfiguration> datasource = new TreeMap<>(
|
||||
String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
/**
|
||||
* transport configuration about dashboard and client
|
||||
* Transport configuration about dashboard and client.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Transport transport = new Transport();
|
||||
|
||||
/**
|
||||
* metric configuration about resource
|
||||
* Metric configuration about resource.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Metric metric = new Metric();
|
||||
|
||||
/**
|
||||
* web servlet configuration <note> when the application is web ,the configuration is
|
||||
* effective </note>
|
||||
* Web servlet configuration when the application is web, the configuration is
|
||||
* effective.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Servlet servlet = new Servlet();
|
||||
|
||||
/**
|
||||
* sentinel filter <note> when the application is web ,the configuration is effective
|
||||
* </note>
|
||||
* Sentinel filter when the application is web, the configuration is effective.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Filter filter = new Filter();
|
||||
|
||||
/**
|
||||
* flow configuration
|
||||
* Sentinel Flow configuration.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Flow flow = new Flow();
|
||||
|
||||
/**
|
||||
* sentinel log configuration {@link LogBase}
|
||||
* Sentinel log configuration {@link LogBase}.
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Log log = new Log();
|
||||
|
||||
public boolean isEager() {
|
||||
@@ -170,7 +163,7 @@ public class SentinelProperties {
|
||||
public static class Flow {
|
||||
|
||||
/**
|
||||
* the cold factor {@link SentinelConfig#COLD_FACTOR}
|
||||
* The cold factor {@link SentinelConfig#COLD_FACTOR}.
|
||||
*/
|
||||
private String coldFactor = "3";
|
||||
|
||||
@@ -187,7 +180,7 @@ public class SentinelProperties {
|
||||
public static class Servlet {
|
||||
|
||||
/**
|
||||
* The process page when the flow control is triggered
|
||||
* The process page when the flow control is triggered.
|
||||
*/
|
||||
private String blockPage;
|
||||
|
||||
@@ -203,17 +196,17 @@ public class SentinelProperties {
|
||||
public static class Metric {
|
||||
|
||||
/**
|
||||
* the metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE}
|
||||
* The metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE}.
|
||||
*/
|
||||
private String fileSingleSize;
|
||||
|
||||
/**
|
||||
* the total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT}
|
||||
* The total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT}.
|
||||
*/
|
||||
private String fileTotalCount;
|
||||
|
||||
/**
|
||||
* charset when sentinel write or search metric file
|
||||
* Charset when sentinel write or search metric file.
|
||||
* {@link SentinelConfig#CHARSET}
|
||||
*/
|
||||
private String charset = "UTF-8";
|
||||
@@ -246,22 +239,28 @@ public class SentinelProperties {
|
||||
public static class Transport {
|
||||
|
||||
/**
|
||||
* sentinel api port,default value is 8719 {@link TransportConfig#SERVER_PORT}
|
||||
* Sentinel api port, default value is 8719 {@link TransportConfig#SERVER_PORT}.
|
||||
*/
|
||||
private String port = "8719";
|
||||
|
||||
/**
|
||||
* sentinel dashboard address, won't try to connect dashboard when address is
|
||||
* empty {@link TransportConfig#CONSOLE_SERVER}
|
||||
* Sentinel dashboard address, won't try to connect dashboard when address is
|
||||
* empty {@link TransportConfig#CONSOLE_SERVER}.
|
||||
*/
|
||||
private String dashboard = "";
|
||||
|
||||
/**
|
||||
* send heartbeat interval millisecond
|
||||
* {@link TransportConfig#HEARTBEAT_INTERVAL_MS}
|
||||
* Send heartbeat interval millisecond
|
||||
* {@link TransportConfig#HEARTBEAT_INTERVAL_MS}.
|
||||
*/
|
||||
private String heartbeatIntervalMs;
|
||||
|
||||
/**
|
||||
* Get heartbeat client local ip. If the client ip not configured, it will be the
|
||||
* address of local host.
|
||||
*/
|
||||
private String clientIp;
|
||||
|
||||
public String getHeartbeatIntervalMs() {
|
||||
return heartbeatIntervalMs;
|
||||
}
|
||||
@@ -286,17 +285,24 @@ public class SentinelProperties {
|
||||
this.dashboard = dashboard;
|
||||
}
|
||||
|
||||
public String getClientIp() {
|
||||
return clientIp;
|
||||
}
|
||||
|
||||
public void setClientIp(String clientIp) {
|
||||
this.clientIp = clientIp;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Filter {
|
||||
|
||||
/**
|
||||
* sentinel filter chain order.
|
||||
* Sentinel filter chain order.
|
||||
*/
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
/**
|
||||
* URL pattern for sentinel filter,default is /*
|
||||
* URL pattern for sentinel filter, default is /*
|
||||
*/
|
||||
private List<String> urlPatterns;
|
||||
|
||||
@@ -320,12 +326,12 @@ public class SentinelProperties {
|
||||
public static class Log {
|
||||
|
||||
/**
|
||||
* sentinel log base dir
|
||||
* Sentinel log base dir.
|
||||
*/
|
||||
private String dir;
|
||||
|
||||
/**
|
||||
* distinguish the log file by pid number
|
||||
* Distinguish the log file by pid number.
|
||||
*/
|
||||
private boolean switchPid = false;
|
||||
|
||||
|
@@ -16,11 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -31,7 +27,9 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
|
||||
import javax.servlet.Filter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
@@ -54,11 +52,6 @@ public class SentinelWebAutoConfiguration {
|
||||
|
||||
SentinelProperties.Filter filterConfig = properties.getFilter();
|
||||
|
||||
if (null == filterConfig) {
|
||||
filterConfig = new SentinelProperties.Filter();
|
||||
properties.setFilter(filterConfig);
|
||||
}
|
||||
|
||||
if (filterConfig.getUrlPatterns() == null
|
||||
|| filterConfig.getUrlPatterns().isEmpty()) {
|
||||
List<String> defaultPatterns = new ArrayList<>();
|
||||
|
@@ -16,23 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
|
||||
@@ -48,9 +32,25 @@ import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
import com.alibaba.csp.sentinel.util.AppNameUtil;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
@@ -74,8 +74,20 @@ public class SentinelAutoConfiguration {
|
||||
@Autowired
|
||||
private Optional<UrlBlockHandler> urlBlockHandlerOptional;
|
||||
|
||||
@Autowired
|
||||
private Optional<RequestOriginParser> requestOriginParserOptional;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR))
|
||||
&& StringUtils.hasText(properties.getLog().getDir())) {
|
||||
System.setProperty(LogBase.LOG_DIR, properties.getLog().getDir());
|
||||
}
|
||||
if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_NAME_USE_PID))
|
||||
&& properties.getLog().isSwitchPid()) {
|
||||
System.setProperty(LogBase.LOG_NAME_USE_PID,
|
||||
String.valueOf(properties.getLog().isSwitchPid()));
|
||||
}
|
||||
if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME))
|
||||
&& StringUtils.hasText(projectName)) {
|
||||
System.setProperty(AppNameUtil.APP_NAME, projectName);
|
||||
@@ -96,6 +108,11 @@ public class SentinelAutoConfiguration {
|
||||
System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS,
|
||||
properties.getTransport().getHeartbeatIntervalMs());
|
||||
}
|
||||
if (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_CLIENT_IP))
|
||||
&& StringUtils.hasText(properties.getTransport().getClientIp())) {
|
||||
System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP,
|
||||
properties.getTransport().getClientIp());
|
||||
}
|
||||
if (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET))
|
||||
&& StringUtils.hasText(properties.getMetric().getCharset())) {
|
||||
System.setProperty(SentinelConfig.CHARSET,
|
||||
@@ -121,18 +138,10 @@ public class SentinelAutoConfiguration {
|
||||
if (StringUtils.hasText(properties.getServlet().getBlockPage())) {
|
||||
WebServletConfig.setBlockPage(properties.getServlet().getBlockPage());
|
||||
}
|
||||
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()));
|
||||
}
|
||||
|
||||
urlBlockHandlerOptional.ifPresent(WebCallbackManager::setUrlBlockHandler);
|
||||
urlCleanerOptional.ifPresent(WebCallbackManager::setUrlCleaner);
|
||||
requestOriginParserOptional.ifPresent(WebCallbackManager::setRequestOriginParser);
|
||||
|
||||
// earlier initialize
|
||||
if (properties.isEager()) {
|
||||
@@ -150,13 +159,15 @@ public class SentinelAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
public SentinelBeanPostProcessor sentinelBeanPostProcessor() {
|
||||
return new SentinelBeanPostProcessor();
|
||||
public SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SentinelDataSourceHandler sentinelDataSourceHandler() {
|
||||
return new SentinelDataSourceHandler();
|
||||
public SentinelDataSourceHandler sentinelDataSourceHandler(
|
||||
DefaultListableBeanFactory beanFactory) {
|
||||
return new SentinelDataSourceHandler(beanFactory);
|
||||
}
|
||||
|
||||
protected static class SentinelConverterConfiguration {
|
||||
|
@@ -16,22 +16,31 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelConstants;
|
||||
import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.type.StandardMethodMetadata;
|
||||
import org.springframework.core.type.classreading.MethodMetadataReadingVisitor;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for RestTemplate
|
||||
*
|
||||
@@ -41,8 +50,14 @@ import org.springframework.web.client.RestTemplate;
|
||||
*/
|
||||
public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(SentinelBeanPostProcessor.class);
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public SentinelBeanPostProcessor(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -60,10 +75,74 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
|
||||
sentinelRestTemplate = beanDefinition.getResolvedFactoryMethod()
|
||||
.getAnnotation(SentinelRestTemplate.class);
|
||||
}
|
||||
// check class and method validation
|
||||
checkSentinelRestTemplate(sentinelRestTemplate, beanName);
|
||||
cache.put(beanName, sentinelRestTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSentinelRestTemplate(SentinelRestTemplate sentinelRestTemplate,
|
||||
String beanName) {
|
||||
checkBlock4RestTemplate(sentinelRestTemplate.blockHandlerClass(),
|
||||
sentinelRestTemplate.blockHandler(), beanName,
|
||||
SentinelConstants.BLOCK_TYPE);
|
||||
checkBlock4RestTemplate(sentinelRestTemplate.fallbackClass(),
|
||||
sentinelRestTemplate.fallback(), beanName,
|
||||
SentinelConstants.FALLBACK_TYPE);
|
||||
}
|
||||
|
||||
private void checkBlock4RestTemplate(Class<?> blockClass, String blockMethod,
|
||||
String beanName, String type) {
|
||||
if (blockClass == void.class && StringUtils.isEmpty(blockMethod)) {
|
||||
return;
|
||||
}
|
||||
if (blockClass != void.class && StringUtils.isEmpty(blockMethod)) {
|
||||
logger.error(
|
||||
"{} class attribute exists but {} method attribute is not exists in bean[{}]",
|
||||
type, type, beanName);
|
||||
throw new IllegalArgumentException(type + " class attribute exists but "
|
||||
+ type + " method attribute is not exists in bean[" + beanName + "]");
|
||||
}
|
||||
else if (blockClass == void.class && !StringUtils.isEmpty(blockMethod)) {
|
||||
logger.error(
|
||||
"{} method attribute exists but {} class attribute is not exists in bean[{}]",
|
||||
type, type, beanName);
|
||||
throw new IllegalArgumentException(type + " method attribute exists but "
|
||||
+ type + " class attribute is not exists in bean[" + beanName + "]");
|
||||
}
|
||||
Class[] args = new Class[] { HttpRequest.class, byte[].class,
|
||||
ClientHttpRequestExecution.class, BlockException.class };
|
||||
String argsStr = Arrays.toString(
|
||||
Arrays.stream(args).map(clazz -> clazz.getSimpleName()).toArray());
|
||||
Method foundMethod = ClassUtils.getStaticMethod(blockClass, blockMethod, args);
|
||||
if (foundMethod == null) {
|
||||
logger.error(
|
||||
"{} static method can not be found in bean[{}]. The right method signature is {}#{}{}, please check your class name, method name and arguments",
|
||||
type, beanName, blockClass.getName(), blockMethod, argsStr);
|
||||
throw new IllegalArgumentException(type
|
||||
+ " static method can not be found in bean[" + beanName
|
||||
+ "]. The right method signature is " + blockClass.getName() + "#"
|
||||
+ blockMethod + argsStr
|
||||
+ ", please check your class name, method name and arguments");
|
||||
}
|
||||
|
||||
if (!ClientHttpResponse.class.isAssignableFrom(foundMethod.getReturnType())) {
|
||||
logger.error(
|
||||
"{} method return value in bean[{}] is not ClientHttpResponse: {}#{}{}",
|
||||
type, beanName, blockClass.getName(), blockMethod, argsStr);
|
||||
throw new IllegalArgumentException(type + " method return value in bean["
|
||||
+ beanName + "] is not ClientHttpResponse: " + blockClass.getName()
|
||||
+ "#" + blockMethod + argsStr);
|
||||
}
|
||||
if (type.equals(SentinelConstants.BLOCK_TYPE)) {
|
||||
BlockClassRegistry.updateBlockHandlerFor(blockClass, blockMethod,
|
||||
foundMethod);
|
||||
}
|
||||
else {
|
||||
BlockClassRegistry.updateFallbackFor(blockClass, blockMethod, foundMethod);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkSentinelProtect(RootBeanDefinition beanDefinition,
|
||||
Class<?> beanType) {
|
||||
return beanType == RestTemplate.class
|
||||
@@ -103,7 +182,7 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
|
||||
SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext
|
||||
.getBean(interceptorBeanName.toString(),
|
||||
SentinelProtectInterceptor.class);
|
||||
restTemplate.getInterceptors().add(sentinelProtectInterceptor);
|
||||
restTemplate.getInterceptors().add(0, sentinelProtectInterceptor);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* <p>
|
||||
* support @EnableCircuitBreaker ,Do nothing
|
||||
*/
|
||||
@Configuration
|
||||
public class SentinelCircuitBreakerConfiguration {
|
||||
}
|
@@ -1,21 +1,16 @@
|
||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
|
||||
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
|
||||
import com.alibaba.csp.sentinel.slots.block.AbstractRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelConstants;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants;
|
||||
@@ -24,16 +19,17 @@ import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePr
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.config.NacosDataSourceProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter;
|
||||
import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
|
||||
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
|
||||
import com.alibaba.csp.sentinel.slots.block.AbstractRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Sentinel {@link ReadableDataSource} Handler Handle the configurations of
|
||||
@@ -44,29 +40,28 @@ import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
* @see JsonConverter
|
||||
* @see XmlConverter
|
||||
*/
|
||||
public class SentinelDataSourceHandler {
|
||||
public class SentinelDataSourceHandler implements SmartInitializingSingleton {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(SentinelDataSourceHandler.class);
|
||||
|
||||
private List<String> dataTypeList = Arrays.asList("json", "xml");
|
||||
|
||||
private List<String> dataSourceBeanNameList = Collections
|
||||
.synchronizedList(new ArrayList<>());
|
||||
private final String DATA_TYPE_FIELD = "dataType";
|
||||
private final String CUSTOM_DATA_TYPE = "custom";
|
||||
private final String CONVERTER_CLASS_FIELD = "converterClass";
|
||||
|
||||
private final String DATATYPE_FIELD = "dataType";
|
||||
private final String CUSTOM_DATATYPE = "custom";
|
||||
private final String CONVERTERCLASS_FIELD = "converterClass";
|
||||
private final DefaultListableBeanFactory beanFactory;
|
||||
|
||||
public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private SentinelProperties sentinelProperties;
|
||||
|
||||
@EventListener(classes = ApplicationStartedEvent.class)
|
||||
public void buildDataSource(ApplicationStartedEvent event) throws Exception {
|
||||
|
||||
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) event
|
||||
.getApplicationContext().getAutowireCapableBeanFactory();
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
// commercialization
|
||||
if (!StringUtils.isEmpty(System.getProperties()
|
||||
.getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) {
|
||||
@@ -101,9 +96,8 @@ public class SentinelDataSourceHandler {
|
||||
AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties
|
||||
.getValidDataSourceProperties();
|
||||
abstractDataSourceProperties.preCheck(dataSourceName);
|
||||
registerBean(beanFactory, abstractDataSourceProperties,
|
||||
dataSourceName + "-sentinel-" + validFields.get(0)
|
||||
+ "-datasource");
|
||||
registerBean(abstractDataSourceProperties, dataSourceName
|
||||
+ "-sentinel-" + validFields.get(0) + "-datasource");
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||
@@ -112,8 +106,7 @@ public class SentinelDataSourceHandler {
|
||||
});
|
||||
}
|
||||
|
||||
private void registerBean(DefaultListableBeanFactory beanFactory,
|
||||
final AbstractDataSourceProperties dataSourceProperties,
|
||||
private void registerBean(final AbstractDataSourceProperties dataSourceProperties,
|
||||
String dataSourceName) {
|
||||
|
||||
Map<String, Object> propertyMap = Arrays
|
||||
@@ -132,8 +125,8 @@ public class SentinelDataSourceHandler {
|
||||
e);
|
||||
}
|
||||
}, HashMap::putAll);
|
||||
propertyMap.put(CONVERTERCLASS_FIELD, dataSourceProperties.getConverterClass());
|
||||
propertyMap.put(DATATYPE_FIELD, dataSourceProperties.getDataType());
|
||||
propertyMap.put(CONVERTER_CLASS_FIELD, dataSourceProperties.getConverterClass());
|
||||
propertyMap.put(DATA_TYPE_FIELD, dataSourceProperties.getDataType());
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(dataSourceProperties.getFactoryBeanName());
|
||||
@@ -141,81 +134,78 @@ public class SentinelDataSourceHandler {
|
||||
propertyMap.forEach((propertyName, propertyValue) -> {
|
||||
Field field = ReflectionUtils.findField(dataSourceProperties.getClass(),
|
||||
propertyName);
|
||||
if (field != null) {
|
||||
if (DATATYPE_FIELD.equals(propertyName)) {
|
||||
String dataType = StringUtils
|
||||
.trimAllWhitespace(propertyValue.toString());
|
||||
if (CUSTOM_DATATYPE.equals(dataType)) {
|
||||
try {
|
||||
if (StringUtils
|
||||
.isEmpty(dataSourceProperties.getConverterClass())) {
|
||||
throw new RuntimeException(
|
||||
"[Sentinel Starter] DataSource " + dataSourceName
|
||||
+ "dataType is custom, please set converter-class "
|
||||
+ "property");
|
||||
}
|
||||
// construct custom Converter with 'converterClass'
|
||||
// configuration and register
|
||||
String customConvertBeanName = "sentinel-"
|
||||
+ dataSourceProperties.getConverterClass();
|
||||
if (!beanFactory.containsBean(customConvertBeanName)) {
|
||||
beanFactory.registerBeanDefinition(customConvertBeanName,
|
||||
BeanDefinitionBuilder
|
||||
.genericBeanDefinition(
|
||||
Class.forName(dataSourceProperties
|
||||
.getConverterClass()))
|
||||
.getBeanDefinition());
|
||||
}
|
||||
builder.addPropertyReference("converter",
|
||||
customConvertBeanName);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||
+ " handle "
|
||||
+ dataSourceProperties.getClass().getSimpleName()
|
||||
+ " error, class name: "
|
||||
+ dataSourceProperties.getConverterClass());
|
||||
throw new RuntimeException(
|
||||
"[Sentinel Starter] DataSource " + dataSourceName
|
||||
+ " handle "
|
||||
+ dataSourceProperties.getClass()
|
||||
.getSimpleName()
|
||||
+ " error, class name: "
|
||||
+ dataSourceProperties.getConverterClass(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!dataTypeList.contains(StringUtils
|
||||
.trimAllWhitespace(propertyValue.toString()))) {
|
||||
if (null == field) {
|
||||
return;
|
||||
}
|
||||
if (DATA_TYPE_FIELD.equals(propertyName)) {
|
||||
String dataType = StringUtils.trimAllWhitespace(propertyValue.toString());
|
||||
if (CUSTOM_DATA_TYPE.equals(dataType)) {
|
||||
try {
|
||||
if (StringUtils
|
||||
.isEmpty(dataSourceProperties.getConverterClass())) {
|
||||
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||
+ dataSourceName + " dataType: " + propertyValue
|
||||
+ " is not support now. please using these types: "
|
||||
+ dataTypeList.toString());
|
||||
+ dataSourceName
|
||||
+ "dataType is custom, please set converter-class "
|
||||
+ "property");
|
||||
}
|
||||
// converter type now support xml or json.
|
||||
// The bean name of these converters wrapped by
|
||||
// 'sentinel-{converterType}-{ruleType}-converter'
|
||||
builder.addPropertyReference("converter",
|
||||
"sentinel-" + propertyValue.toString() + "-"
|
||||
+ dataSourceProperties.getRuleType().getName()
|
||||
+ "-converter");
|
||||
// construct custom Converter with 'converterClass'
|
||||
// configuration and register
|
||||
String customConvertBeanName = "sentinel-"
|
||||
+ dataSourceProperties.getConverterClass();
|
||||
if (!this.beanFactory.containsBean(customConvertBeanName)) {
|
||||
this.beanFactory.registerBeanDefinition(customConvertBeanName,
|
||||
BeanDefinitionBuilder
|
||||
.genericBeanDefinition(
|
||||
Class.forName(dataSourceProperties
|
||||
.getConverterClass()))
|
||||
.getBeanDefinition());
|
||||
}
|
||||
builder.addPropertyReference("converter", customConvertBeanName);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.error("[Sentinel Starter] DataSource " + dataSourceName
|
||||
+ " handle "
|
||||
+ dataSourceProperties.getClass().getSimpleName()
|
||||
+ " error, class name: "
|
||||
+ dataSourceProperties.getConverterClass());
|
||||
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||
+ dataSourceName + " handle "
|
||||
+ dataSourceProperties.getClass().getSimpleName()
|
||||
+ " error, class name: "
|
||||
+ dataSourceProperties.getConverterClass(), e);
|
||||
}
|
||||
}
|
||||
else if (CONVERTERCLASS_FIELD.equals(propertyName)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// wired properties
|
||||
Optional.ofNullable(propertyValue)
|
||||
.ifPresent(v -> builder.addPropertyValue(propertyName, v));
|
||||
if (!dataTypeList.contains(
|
||||
StringUtils.trimAllWhitespace(propertyValue.toString()))) {
|
||||
throw new RuntimeException("[Sentinel Starter] DataSource "
|
||||
+ dataSourceName + " dataType: " + propertyValue
|
||||
+ " is not support now. please using these types: "
|
||||
+ dataTypeList.toString());
|
||||
}
|
||||
// converter type now support xml or json.
|
||||
// The bean name of these converters wrapped by
|
||||
// 'sentinel-{converterType}-{ruleType}-converter'
|
||||
builder.addPropertyReference("converter",
|
||||
"sentinel-" + propertyValue.toString() + "-"
|
||||
+ dataSourceProperties.getRuleType().getName()
|
||||
+ "-converter");
|
||||
}
|
||||
}
|
||||
else if (CONVERTER_CLASS_FIELD.equals(propertyName)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// wired properties
|
||||
Optional.ofNullable(propertyValue)
|
||||
.ifPresent(v -> builder.addPropertyValue(propertyName, v));
|
||||
}
|
||||
});
|
||||
|
||||
beanFactory.registerBeanDefinition(dataSourceName, builder.getBeanDefinition());
|
||||
this.beanFactory.registerBeanDefinition(dataSourceName,
|
||||
builder.getBeanDefinition());
|
||||
// init in Spring
|
||||
AbstractDataSource newDataSource = (AbstractDataSource) beanFactory
|
||||
AbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory
|
||||
.getBean(dataSourceName);
|
||||
|
||||
logAndCheckRuleType(newDataSource, dataSourceName,
|
||||
@@ -234,7 +224,6 @@ public class SentinelDataSourceHandler {
|
||||
DegradeRuleManager.register2Property(newDataSource.getProperty());
|
||||
}
|
||||
}
|
||||
dataSourceBeanNameList.add(dataSourceName);
|
||||
}
|
||||
|
||||
private void logAndCheckRuleType(AbstractDataSource dataSource, String dataSourceName,
|
||||
@@ -282,9 +271,4 @@ public class SentinelDataSourceHandler {
|
||||
+ ruleClass.getSimpleName() + ">. Class: " + ruleConfig.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getDataSourceBeanNameList() {
|
||||
return dataSourceBeanNameList;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel.custom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.alibaba.csp.sentinel.Entry;
|
||||
import com.alibaba.csp.sentinel.SphU;
|
||||
import com.alibaba.csp.sentinel.Tracer;
|
||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate;
|
||||
@@ -29,27 +30,23 @@ import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.alibaba.csp.sentinel.Entry;
|
||||
import com.alibaba.csp.sentinel.SphU;
|
||||
import com.alibaba.csp.sentinel.Tracer;
|
||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
|
||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Interceptor using by SentinelRestTemplate
|
||||
*
|
||||
* @author fangjian
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(SentinelProtectInterceptor.class);
|
||||
|
||||
private SentinelRestTemplate sentinelRestTemplate;
|
||||
private final SentinelRestTemplate sentinelRestTemplate;
|
||||
|
||||
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) {
|
||||
this.sentinelRestTemplate = sentinelRestTemplate;
|
||||
@@ -82,18 +79,7 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return handleBlockException(request, body, execution,
|
||||
(BlockException) e);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof IllegalStateException) {
|
||||
throw (IllegalStateException) ex;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"sentinel handle BlockException error: " + ex.getMessage(),
|
||||
ex);
|
||||
}
|
||||
return handleBlockException(request, body, execution, (BlockException) e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -109,84 +95,49 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
|
||||
}
|
||||
|
||||
private ClientHttpResponse handleBlockException(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution, BlockException ex) throws Exception {
|
||||
ClientHttpRequestExecution execution, BlockException ex) {
|
||||
Object[] args = new Object[] { request, body, execution, ex };
|
||||
// handle degrade
|
||||
if (isDegradeFailure(ex)) {
|
||||
Method method = extractFallbackMethod(sentinelRestTemplate.fallback(),
|
||||
Method fallbackMethod = extractFallbackMethod(sentinelRestTemplate.fallback(),
|
||||
sentinelRestTemplate.fallbackClass());
|
||||
if (method != null) {
|
||||
return (ClientHttpResponse) method.invoke(null, args);
|
||||
if (fallbackMethod != null) {
|
||||
return methodInvoke(fallbackMethod, args);
|
||||
}
|
||||
else {
|
||||
return new SentinelClientHttpResponse();
|
||||
}
|
||||
}
|
||||
// handle block
|
||||
// handle flow
|
||||
Method blockHandler = extractBlockHandlerMethod(
|
||||
sentinelRestTemplate.blockHandler(),
|
||||
sentinelRestTemplate.blockHandlerClass());
|
||||
if (blockHandler != null) {
|
||||
return (ClientHttpResponse) blockHandler.invoke(null, args);
|
||||
return methodInvoke(blockHandler, args);
|
||||
}
|
||||
else {
|
||||
return new SentinelClientHttpResponse();
|
||||
}
|
||||
}
|
||||
|
||||
private ClientHttpResponse methodInvoke(Method method, Object... args) {
|
||||
try {
|
||||
return (ClientHttpResponse) method.invoke(null, args);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Method extractFallbackMethod(String fallback, Class<?> fallbackClass) {
|
||||
if (StringUtil.isBlank(fallback) || fallbackClass == void.class) {
|
||||
return null;
|
||||
}
|
||||
Method cachedMethod = BlockClassRegistry.lookupFallback(fallbackClass, fallback);
|
||||
Class[] args = new Class[] { HttpRequest.class, byte[].class,
|
||||
ClientHttpRequestExecution.class, BlockException.class };
|
||||
if (cachedMethod == null) {
|
||||
cachedMethod = ClassUtils.getStaticMethod(fallbackClass, fallback, args);
|
||||
if (cachedMethod != null) {
|
||||
if (!ClientHttpResponse.class
|
||||
.isAssignableFrom(cachedMethod.getReturnType())) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"the return type of method [%s] in class [%s] is not ClientHttpResponse in degrade",
|
||||
cachedMethod.getName(), fallbackClass.getCanonicalName()));
|
||||
}
|
||||
BlockClassRegistry.updateFallbackFor(fallbackClass, fallback,
|
||||
cachedMethod);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Cannot find method [%s] in class [%s] with parameters %s in degrade",
|
||||
fallback, fallbackClass.getCanonicalName(), Arrays.asList(args)));
|
||||
}
|
||||
}
|
||||
return cachedMethod;
|
||||
return BlockClassRegistry.lookupFallback(fallbackClass, fallback);
|
||||
}
|
||||
|
||||
private Method extractBlockHandlerMethod(String block, Class<?> blockClass) {
|
||||
if (StringUtil.isBlank(block) || blockClass == void.class) {
|
||||
return null;
|
||||
}
|
||||
Method cachedMethod = BlockClassRegistry.lookupBlockHandler(blockClass, block);
|
||||
Class[] args = new Class[] { HttpRequest.class, byte[].class,
|
||||
ClientHttpRequestExecution.class, BlockException.class };
|
||||
if (cachedMethod == null) {
|
||||
cachedMethod = ClassUtils.getStaticMethod(blockClass, block, args);
|
||||
if (cachedMethod != null) {
|
||||
if (!ClientHttpResponse.class
|
||||
.isAssignableFrom(cachedMethod.getReturnType())) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"the return type of method [%s] in class [%s] is not ClientHttpResponse in flow control",
|
||||
cachedMethod.getName(), blockClass.getCanonicalName()));
|
||||
}
|
||||
BlockClassRegistry.updateBlockHandlerFor(blockClass, block, cachedMethod);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Cannot find method [%s] in class [%s] with parameters %s in flow control",
|
||||
block, blockClass.getCanonicalName(), Arrays.asList(args)));
|
||||
}
|
||||
}
|
||||
return cachedMethod;
|
||||
return BlockClassRegistry.lookupBlockHandler(blockClass, block);
|
||||
}
|
||||
|
||||
private boolean isDegradeFailure(BlockException ex) {
|
||||
|
@@ -16,26 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig;
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.log.LogBase;
|
||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
|
||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||
import org.springframework.cloud.alibaba.sentinel.custom.SentinelDataSourceHandler;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Endpoint for Sentinel, contains ans properties and rules
|
||||
@@ -44,43 +39,39 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
|
||||
@Endpoint(id = "sentinel")
|
||||
public class SentinelEndpoint {
|
||||
|
||||
@Autowired
|
||||
private SentinelProperties sentinelProperties;
|
||||
private final SentinelProperties sentinelProperties;
|
||||
|
||||
@Autowired
|
||||
private SentinelDataSourceHandler dataSourceHandler;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
public SentinelEndpoint(SentinelProperties sentinelProperties) {
|
||||
this.sentinelProperties = sentinelProperties;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Map<String, Object> invoke() {
|
||||
final Map<String, Object> result = new HashMap<>();
|
||||
if (sentinelProperties.isEnabled()) {
|
||||
|
||||
List<FlowRule> flowRules = FlowRuleManager.getRules();
|
||||
List<DegradeRule> degradeRules = DegradeRuleManager.getRules();
|
||||
List<SystemRule> systemRules = SystemRuleManager.getRules();
|
||||
List<ParamFlowRule> paramFlowRules = ParamFlowRuleManager.getRules();
|
||||
result.put("properties", sentinelProperties);
|
||||
result.put("FlowRules", flowRules);
|
||||
result.put("DegradeRules", degradeRules);
|
||||
result.put("SystemRules", systemRules);
|
||||
result.put("ParamFlowRule", paramFlowRules);
|
||||
result.put("datasources", new HashMap<String, Object>());
|
||||
dataSourceHandler.getDataSourceBeanNameList().forEach(dataSourceBeanName -> {
|
||||
ReadableDataSource dataSource = applicationContext.getBean(dataSourceBeanName,
|
||||
ReadableDataSource.class);
|
||||
try {
|
||||
((HashMap) result.get("datasources")).put(dataSourceBeanName,
|
||||
dataSource.loadConfig());
|
||||
}
|
||||
catch (Exception e) {
|
||||
((HashMap) result.get("datasources")).put(dataSourceBeanName,
|
||||
"load error: " + e.getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
result.put("logDir", LogBase.getLogBaseDir());
|
||||
result.put("logUsePid", LogBase.isLogNameUsePid());
|
||||
result.put("blockPage", WebServletConfig.getBlockPage());
|
||||
result.put("metricsFileSize", SentinelConfig.singleMetricFileSize());
|
||||
result.put("metricsFileCharset", SentinelConfig.charset());
|
||||
result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount());
|
||||
result.put("consoleServer", TransportConfig.getConsoleServer());
|
||||
result.put("clientIp", TransportConfig.getHeartbeatClientIp());
|
||||
result.put("heartbeatIntervalMs", TransportConfig.getHeartbeatIntervalMs());
|
||||
result.put("clientPort", TransportConfig.getPort());
|
||||
result.put("coldFactor", sentinelProperties.getFlow().getColdFactor());
|
||||
result.put("filter", sentinelProperties.getFilter());
|
||||
result.put("datasource", sentinelProperties.getDatasource());
|
||||
|
||||
final Map<String, Object> rules = new HashMap<>();
|
||||
result.put("rules", rules);
|
||||
rules.put("flowRules", FlowRuleManager.getRules());
|
||||
rules.put("degradeRules", DegradeRuleManager.getRules());
|
||||
rules.put("systemRules", SystemRuleManager.getRules());
|
||||
rules.put("authorityRule", AuthorityRuleManager.getRules());
|
||||
rules.put("paramFlowRule", ParamFlowRuleManager.getRules());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -34,8 +34,8 @@ public class SentinelEndpointAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public SentinelEndpoint sentinelEndPoint() {
|
||||
return new SentinelEndpoint();
|
||||
public SentinelEndpoint sentinelEndPoint(SentinelProperties sentinelProperties) {
|
||||
return new SentinelEndpoint(sentinelProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,11 @@
|
||||
"defaultValue": "8719",
|
||||
"description": "sentinel api port."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.sentinel.transport.clientIp",
|
||||
"type": "java.lang.String",
|
||||
"description": "sentinel client ip connect to dashboard."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.sentinel.transport.dashboard",
|
||||
"type": "java.lang.String",
|
||||
|
@@ -3,3 +3,6 @@ org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\
|
||||
org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
|
||||
org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\
|
||||
org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration
|
||||
|
||||
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
|
||||
org.springframework.cloud.alibaba.sentinel.custom.SentinelCircuitBreakerConfiguration
|
||||
|
Reference in New Issue
Block a user