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>
</developer>
<developer>
<name>fangjian</name>
<name>Jim Fang</name>
<email>fangjian0423@gmail.com</email>
<organization>Alibaba</organization>
<url>https://github.com/fangjian0423</url>
</developer>
<developer>
<name>xiaolongzuo</name>

View File

@ -166,7 +166,7 @@ NOTE: 在使用 RocketMQ Binder 的同时也可以配置 rocketmq.** 用于触
MessageBuilder builder = MessageBuilder.withPayload(msg)
.setHeader(RocketMQHeaders.TAGS, "binder")
.setHeader(RocketMQHeaders.KEYS, "my-key")
.setHeader("DELAY", "1");
.setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "1");
Message message = builder.build();
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.**
=== 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:
@ -165,7 +165,7 @@ For example, `TAGS`, `DELAY`, `TRANSACTIONAL_ARG`, `KEYS`, `WAIT_STORE_MSG_OK`,
MessageBuilder builder = MessageBuilder.withPayload(msg)
.setHeader(RocketMQHeaders.TAGS, "binder")
.setHeader(RocketMQHeaders.KEYS, "my-key")
.setHeader("DELAY", "1");
.setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "1");
Message message = builder.build();
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
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:
@ -278,7 +278,7 @@ If you want to use Sentinel Starter with Zuul, you need to add the `spring-cloud
=== 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:
@ -299,6 +299,8 @@ If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add t
</dependency>
```
include::circuitbreaker-sentinel.adoc[]
=== Sentinel Endpoint
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.boot.autoconfigure.AutoConfigureAfter;
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.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
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.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment;
import org.springframework.core.type.MethodMetadata;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
@ -56,8 +59,8 @@ import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
@ConditionalOnClass(name = { "org.springframework.web.client.RestTemplate" })
@AutoConfigureAfter(name = {
"org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration" })
public class DubboLoadBalancedRestTemplateAutoConfiguration
implements BeanClassLoaderAware, SmartInitializingSingleton {
public class DubboLoadBalancedRestTemplateAutoConfiguration implements
BeanClassLoaderAware, ApplicationContextAware, SmartInitializingSingleton {
private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class;
@ -89,6 +92,9 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
@Autowired(required = false)
private Map<String, RestTemplate> restTemplates = Collections.emptyMap();
@Nullable
private ApplicationContext applicationContext;
private ClassLoader classLoader;
/**
@ -111,18 +117,21 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
* {@link SmartInitializingSingleton} beans or
* {@link RestTemplateCustomizer#customize(RestTemplate) customization})
*/
@EventListener(ApplicationStartedEvent.class)
public void adaptRestTemplates() {
@EventListener(ContextRefreshedEvent.class)
public void adaptRestTemplates(ContextRefreshedEvent event) {
DubboTransportedAttributesResolver attributesResolver = new DubboTransportedAttributesResolver(
environment);
if (event.getApplicationContext() == this.applicationContext) {
for (Map.Entry<String, RestTemplate> entry : restTemplates.entrySet()) {
String beanName = entry.getKey();
Map<String, Object> dubboTranslatedAttributes = getDubboTranslatedAttributes(
beanName, attributesResolver);
if (!CollectionUtils.isEmpty(dubboTranslatedAttributes)) {
adaptRestTemplate(entry.getValue(), dubboTranslatedAttributes);
DubboTransportedAttributesResolver attributesResolver = new DubboTransportedAttributesResolver(
environment);
for (Map.Entry<String, RestTemplate> entry : restTemplates.entrySet()) {
String beanName = entry.getKey();
Map<String, Object> dubboTranslatedAttributes = getDubboTranslatedAttributes(
beanName, attributesResolver);
if (!CollectionUtils.isEmpty(dubboTranslatedAttributes)) {
adaptRestTemplate(entry.getValue(), dubboTranslatedAttributes);
}
}
}
}
@ -132,7 +141,7 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
* {@link DubboTransported @DubboTransported}
*
* @param beanName the bean name of {@link LoadBalanced @LoadBalanced}
* {@link RestTemplate}
* {@link RestTemplate}
* @param attributesResolver {@link DubboTransportedAttributesResolver}
* @return non-null {@link Map}
*/
@ -144,10 +153,10 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
MethodMetadata factoryMethodMetadata = annotatedBeanDefinition
.getFactoryMethodMetadata();
attributes = factoryMethodMetadata != null
? Optional.ofNullable(factoryMethodMetadata
.getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME)).orElse(attributes)
: Collections.emptyMap();
attributes = factoryMethodMetadata != null ? Optional
.ofNullable(factoryMethodMetadata
.getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME))
.orElse(attributes) : Collections.emptyMap();
}
return attributesResolver.resolve(attributes);
}
@ -158,8 +167,8 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
*
* @param restTemplate {@link LoadBalanced @LoadBalanced} {@link RestTemplate} Bean
* @param dubboTranslatedAttributes the annotation dubboTranslatedAttributes
* {@link RestTemplate} bean being annotated
* {@link DubboTransported @DubboTransported}
* {@link RestTemplate} bean being annotated
* {@link DubboTransported @DubboTransported}
*/
private void adaptRestTemplate(RestTemplate restTemplate,
Map<String, Object> dubboTranslatedAttributes) {
@ -188,4 +197,9 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration
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 {
@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;
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.core.type.MethodMetadata;
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;
@ -171,12 +170,6 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
&& checkMethodMetadataReadingVisitor(beanDefinition);
}
// private boolean checkStandardMethodMetadata(RootBeanDefinition beanDefinition) {
// return beanDefinition.getSource() instanceof StandardMethodMetadata
// && ((StandardMethodMetadata) beanDefinition.getSource())
// .isAnnotated(SentinelRestTemplate.class.getName());
// }
private boolean checkMethodMetadataReadingVisitor(RootBeanDefinition beanDefinition) {
return beanDefinition.getSource() instanceof MethodMetadata
&& ((MethodMetadata) beanDefinition.getSource())