1
0
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'

This commit is contained in:
mercyblitz 2019-09-12 14:10:50 +08:00
commit 0e82361ff4
8 changed files with 118 additions and 34 deletions

View File

@ -45,8 +45,10 @@
<email>flystar32@163.com</email> <email>flystar32@163.com</email>
</developer> </developer>
<developer> <developer>
<name>fangjian</name> <name>Jim Fang</name>
<email>fangjian0423@gmail.com</email> <email>fangjian0423@gmail.com</email>
<organization>Alibaba</organization>
<url>https://github.com/fangjian0423</url>
</developer> </developer>
<developer> <developer>
<name>xiaolongzuo</name> <name>xiaolongzuo</name>

View File

@ -166,7 +166,7 @@ NOTE: 在使用 RocketMQ Binder 的同时也可以配置 rocketmq.** 用于触
MessageBuilder builder = MessageBuilder.withPayload(msg) MessageBuilder builder = MessageBuilder.withPayload(msg)
.setHeader(RocketMQHeaders.TAGS, "binder") .setHeader(RocketMQHeaders.TAGS, "binder")
.setHeader(RocketMQHeaders.KEYS, "my-key") .setHeader(RocketMQHeaders.KEYS, "my-key")
.setHeader("DELAY", "1"); .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "1");
Message message = builder.build(); Message message = builder.build();
output().send(message); output().send(message);
``` ```

View File

@ -0,0 +1,73 @@
=== Circuit Breaker: Spring Cloud Circuit Breaker With Sentinel & Configuring Sentinel Circuit Breakers
==== Default Configuration
To provide a default configuration for all of your circuit breakers create a `Customizer` bean that is passed a
`SentinelCircuitBreakerFactory` or `ReactiveSentinelCircuitBreakerFactory`.
The `configureDefault` method can be used to provide a default configuration.
====
[source,java]
----
@Bean
public Customizer<SentinelCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id)
.build());
}
----
====
You can choose to provide default circuit breaking rules via `SentinelConfigBuilder#rules(rules)`.
You can also choose to load circuit breaking rules later elsewhere using
`DegradeRuleManager.loadRules(rules)` API of Sentinel, or via Sentinel dashboard.
===== Reactive Example
====
[source,java]
----
@Bean
public Customizer<ReactiveSentinelCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id)
.build());
}
----
====
==== Specific Circuit Breaker Configuration
Similarly to providing a default configuration, you can create a `Customizer` bean this is passed a
`SentinelCircuitBreakerFactory`.
====
[source,java]
----
@Bean
public Customizer<SentinelCircuitBreakerFactory> slowCustomizer() {
String slowId = "slow";
List<DegradeRule> rules = Collections.singletonList(
new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(100)
.setTimeWindow(10)
);
return factory -> factory.configure(builder -> builder.rules(rules), slowId);
}
----
====
===== Reactive Example
====
[source,java]
----
@Bean
public Customizer<ReactiveSentinelCircuitBreakerFactory> customizer() {
List<DegradeRule> rules = Collections.singletonList(
new DegradeRule().setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(100)
.setTimeWindow(10)
);
return factory -> factory.configure(builder -> builder.rules(rules), "foo", "bar");
}
----
====

View File

@ -114,7 +114,7 @@ All the message types in this code are provided by the `spring-messaging`module.
**The lower layer of Spring Cloud Stream also implements various code abstractions based on the previous code.** **The lower layer of Spring Cloud Stream also implements various code abstractions based on the previous code.**
=== How to use Spring Cloud Alibaba RocketMQ Binder ### === How to use Spring Cloud Alibaba RocketMQ Binder
For using the Spring Cloud Alibaba RocketMQ Binder, you just need to add it to your Spring Cloud Stream application, using the following Maven coordinates: For using the Spring Cloud Alibaba RocketMQ Binder, you just need to add it to your Spring Cloud Stream application, using the following Maven coordinates:
@ -165,7 +165,7 @@ For example, `TAGS`, `DELAY`, `TRANSACTIONAL_ARG`, `KEYS`, `WAIT_STORE_MSG_OK`,
MessageBuilder builder = MessageBuilder.withPayload(msg) MessageBuilder builder = MessageBuilder.withPayload(msg)
.setHeader(RocketMQHeaders.TAGS, "binder") .setHeader(RocketMQHeaders.TAGS, "binder")
.setHeader(RocketMQHeaders.KEYS, "my-key") .setHeader(RocketMQHeaders.KEYS, "my-key")
.setHeader("DELAY", "1"); .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "1");
Message message = builder.build(); Message message = builder.build();
output().send(message); output().send(message);
``` ```

View File

@ -255,7 +255,7 @@ To learn more about how dynamic data sources work in Sentinel, refer to https://
=== Support Zuul === Support Zuul
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81[参考 Sentinel 网关限流] Refer https://github.com/alibaba/Sentinel/wiki/API-Gateway-Flow-Control[API Gateway Flow Control]
If you want to use Sentinel Starter with Zuul, you need to add the `spring-cloud-alibaba-sentinel-gateway` dependency, and you need to add the `spring-cloud-starter-netflix-zuul` dependency to let Zuul AutoConfiguration class in the gateway module takes effect: If you want to use Sentinel Starter with Zuul, you need to add the `spring-cloud-alibaba-sentinel-gateway` dependency, and you need to add the `spring-cloud-starter-netflix-zuul` dependency to let Zuul AutoConfiguration class in the gateway module takes effect:
@ -278,7 +278,7 @@ If you want to use Sentinel Starter with Zuul, you need to add the `spring-cloud
=== Support Spring Cloud Gateway === Support Spring Cloud Gateway
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81[参考 Sentinel 网关限流] Refer https://github.com/alibaba/Sentinel/wiki/API-Gateway-Flow-Control[API Gateway Flow Control]
If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add the `spring-cloud-alibaba-sentinel-gateway` dependency and add the `spring-cloud-starter-gateway` dependency to let Spring Cloud Gateway AutoConfiguration class in the module takes effect: If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add the `spring-cloud-alibaba-sentinel-gateway` dependency and add the `spring-cloud-starter-gateway` dependency to let Spring Cloud Gateway AutoConfiguration class in the module takes effect:
@ -299,6 +299,8 @@ If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add t
</dependency> </dependency>
``` ```
include::circuitbreaker-sentinel.adoc[]
=== Sentinel Endpoint === Sentinel Endpoint
Sentinel provides an Endpoint internally with a corresponding endpoint id of `sentinel`. Sentinel provides an Endpoint internally with a corresponding endpoint id of `sentinel`.

View File

@ -25,16 +25,19 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -56,8 +59,8 @@ import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
@ConditionalOnClass(name = { "org.springframework.web.client.RestTemplate" }) @ConditionalOnClass(name = { "org.springframework.web.client.RestTemplate" })
@AutoConfigureAfter(name = { @AutoConfigureAfter(name = {
"org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration" }) "org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration" })
public class DubboLoadBalancedRestTemplateAutoConfiguration public class DubboLoadBalancedRestTemplateAutoConfiguration implements
implements BeanClassLoaderAware, SmartInitializingSingleton { BeanClassLoaderAware, ApplicationContextAware, SmartInitializingSingleton {
private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class; private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class;
@ -89,6 +92,9 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
@Autowired(required = false) @Autowired(required = false)
private Map<String, RestTemplate> restTemplates = Collections.emptyMap(); private Map<String, RestTemplate> restTemplates = Collections.emptyMap();
@Nullable
private ApplicationContext applicationContext;
private ClassLoader classLoader; private ClassLoader classLoader;
/** /**
@ -111,8 +117,10 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
* {@link SmartInitializingSingleton} beans or * {@link SmartInitializingSingleton} beans or
* {@link RestTemplateCustomizer#customize(RestTemplate) customization}) * {@link RestTemplateCustomizer#customize(RestTemplate) customization})
*/ */
@EventListener(ApplicationStartedEvent.class) @EventListener(ContextRefreshedEvent.class)
public void adaptRestTemplates() { public void adaptRestTemplates(ContextRefreshedEvent event) {
if (event.getApplicationContext() == this.applicationContext) {
DubboTransportedAttributesResolver attributesResolver = new DubboTransportedAttributesResolver( DubboTransportedAttributesResolver attributesResolver = new DubboTransportedAttributesResolver(
environment); environment);
@ -126,6 +134,7 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
} }
} }
} }
}
/** /**
* Gets the annotation attributes {@link RestTemplate} bean being annotated * Gets the annotation attributes {@link RestTemplate} bean being annotated
@ -144,10 +153,10 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition; AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
MethodMetadata factoryMethodMetadata = annotatedBeanDefinition MethodMetadata factoryMethodMetadata = annotatedBeanDefinition
.getFactoryMethodMetadata(); .getFactoryMethodMetadata();
attributes = factoryMethodMetadata != null attributes = factoryMethodMetadata != null ? Optional
? Optional.ofNullable(factoryMethodMetadata .ofNullable(factoryMethodMetadata
.getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME)).orElse(attributes) .getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME))
: Collections.emptyMap(); .orElse(attributes) : Collections.emptyMap();
} }
return attributesResolver.resolve(attributes); return attributesResolver.resolve(attributes);
} }
@ -188,4 +197,9 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
this.classLoader = classLoader; this.classLoader = classLoader;
} }
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
} }

View File

@ -7,7 +7,7 @@ import org.apache.dubbo.config.annotation.Reference;
*/ */
public class FooServiceConsumer { public class FooServiceConsumer {
@Reference(version = "${foo.service.version}", application = "${dubbo.application.id}", url = "dubbo://localhost:12345", timeout = 30000) @Reference(version = "${foo.service.version}", application = "${dubbo.application.id}", url = "dubbo://localhost:12345?version=1.0.0", timeout = 30000)
private FooService fooService; private FooService fooService;
public String hello(String name) { public String hello(String name) {

View File

@ -31,7 +31,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
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.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
@ -171,12 +170,6 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
&& checkMethodMetadataReadingVisitor(beanDefinition); && checkMethodMetadataReadingVisitor(beanDefinition);
} }
// private boolean checkStandardMethodMetadata(RootBeanDefinition beanDefinition) {
// return beanDefinition.getSource() instanceof StandardMethodMetadata
// && ((StandardMethodMetadata) beanDefinition.getSource())
// .isAnnotated(SentinelRestTemplate.class.getName());
// }
private boolean checkMethodMetadataReadingVisitor(RootBeanDefinition beanDefinition) { private boolean checkMethodMetadataReadingVisitor(RootBeanDefinition beanDefinition) {
return beanDefinition.getSource() instanceof MethodMetadata return beanDefinition.getSource() instanceof MethodMetadata
&& ((MethodMetadata) beanDefinition.getSource()) && ((MethodMetadata) beanDefinition.getSource())