From 1e26df1aa14aa0380d5099866d6712b998237f63 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Mon, 2 Dec 2019 13:38:33 +0800 Subject: [PATCH 1/4] Add property to disable Sentinel auto-configuration --- .../ReactiveSentinelCircuitBreakerAutoConfiguration.java | 3 +++ .../sentinel/SentinelCircuitBreakerAutoConfiguration.java | 3 +++ .../META-INF/additional-spring-configuration-metadata.json | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java index 14a7bc18..974ad2cf 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java @@ -24,6 +24,7 @@ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory; import org.springframework.context.annotation.Bean; @@ -35,6 +36,8 @@ import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnClass( name = { "reactor.core.publisher.Mono", "reactor.core.publisher.Flux" }) +@ConditionalOnProperty(name = "spring.cloud.circuitbreaker.sentinel.enabled", + havingValue = "true", matchIfMissing = true) public class ReactiveSentinelCircuitBreakerAutoConfiguration { @Bean diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java index 2d22ba07..d4b37325 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java @@ -26,6 +26,7 @@ import com.alibaba.csp.sentinel.SphU; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.context.annotation.Bean; @@ -38,6 +39,8 @@ import org.springframework.context.annotation.Configuration; */ @Configuration @ConditionalOnClass({ SphU.class }) +@ConditionalOnProperty(name = "spring.cloud.circuitbreaker.sentinel.enabled", + havingValue = "true", matchIfMissing = true) public class SentinelCircuitBreakerAutoConfiguration { @Bean diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..44597a6d --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,7 @@ +{"properties": [ + { + "name": "spring.cloud.circuitbreaker.sentinel.enabled", + "type": "java.lang.Boolean", + "description": "enable sentinel circuitbreaker or not." + } +]} From 224ef57307d6cb1d1c3a69293878a525ce4fd7d2 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Mon, 2 Dec 2019 12:54:44 +0800 Subject: [PATCH 2/4] Add default values for some configuration items --- .../java/com/alibaba/cloud/nacos/NacosConfigProperties.java | 2 +- .../META-INF/additional-spring-configuration-metadata.json | 1 + .../com/alibaba/cloud/nacos/NacosDiscoveryProperties.java | 2 +- .../META-INF/additional-spring-configuration-metadata.json | 1 + .../datasource/config/NacosDataSourceProperties.java | 6 +----- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java index cd7461e4..f5cee2c6 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java @@ -80,7 +80,7 @@ public class NacosConfigProperties { .resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}"); if (StringUtils.isEmpty(serverAddr)) { serverAddr = environment - .resolvePlaceholders("${spring.cloud.nacos.server-addr:}"); + .resolvePlaceholders("${spring.cloud.nacos.server-addr:localhost:8848}"); } this.setServerAddr(serverAddr); } diff --git a/spring-cloud-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json index c9c87261..3d322070 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -3,6 +3,7 @@ { "name": "spring.cloud.nacos.server-addr", "type": "java.lang.String", + "defaultValue": "localhost:8848", "description": "nacos server address." }, { diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java index 1b2488d7..ed54e88e 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java @@ -431,7 +431,7 @@ public class NacosDiscoveryProperties { .resolvePlaceholders("${spring.cloud.nacos.discovery.server-addr:}"); if (StringUtils.isEmpty(serverAddr)) { serverAddr = env - .resolvePlaceholders("${spring.cloud.nacos.server-addr:}"); + .resolvePlaceholders("${spring.cloud.nacos.server-addr:localhost:8848}"); } this.setServerAddr(serverAddr); } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 2f0718f9..b3dc069b 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -2,6 +2,7 @@ { "name": "spring.cloud.nacos.server-addr", "type": "java.lang.String", + "defaultValue": "localhost:8848", "description": "nacos server address." }, { diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java index cbb63e8e..3fc74945 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java @@ -54,11 +54,7 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { public void preCheck(String dataSourceName) { if (StringUtils.isEmpty(serverAddr)) { serverAddr = this.getEnv().getProperty( - "spring.cloud.sentinel.datasource.nacos.server-addr", ""); - if (StringUtils.isEmpty(serverAddr)) { - throw new IllegalArgumentException( - "NacosDataSource server-addr is empty"); - } + "spring.cloud.sentinel.datasource.nacos.server-addr", "localhost:8848"); } } From d79207c64b65680e45c399cb31f19e8b176e5047 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Wed, 4 Dec 2019 09:23:34 +0800 Subject: [PATCH 3/4] Support seata feign loadbalancer --- spring-cloud-alibaba-seata/pom.xml | 6 ++ .../SeataFeignBlockingLoadBalancerClient.java | 95 +++++++++++++++++++ .../seata/feign/SeataFeignObjectWrapper.java | 39 ++++++++ 3 files changed, 140 insertions(+) create mode 100644 spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java diff --git a/spring-cloud-alibaba-seata/pom.xml b/spring-cloud-alibaba-seata/pom.xml index 5f4a2802..216008cc 100644 --- a/spring-cloud-alibaba-seata/pom.xml +++ b/spring-cloud-alibaba-seata/pom.xml @@ -38,6 +38,12 @@ true + + org.springframework.cloud + spring-cloud-loadbalancer + true + + org.springframework.cloud spring-cloud-starter-netflix-ribbon diff --git a/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java b/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java new file mode 100644 index 00000000..3ad4a09a --- /dev/null +++ b/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013-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 + * + * https://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 com.alibaba.cloud.seata.feign; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import feign.Client; +import feign.Request; +import feign.Response; +import io.seata.core.context.RootContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; +import org.springframework.http.HttpStatus; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * @author yuhuangbin + */ +public class SeataFeignBlockingLoadBalancerClient implements Client { + + private static final Log LOG = LogFactory + .getLog(SeataFeignBlockingLoadBalancerClient.class); + + private final Client delegate; + + private final BlockingLoadBalancerClient loadBalancerClient; + + SeataFeignBlockingLoadBalancerClient(Client delegate, + BlockingLoadBalancerClient loadBalancerClient) { + this.delegate = delegate; + this.loadBalancerClient = loadBalancerClient; + } + + @Override + public Response execute(Request request, Request.Options options) throws IOException { + final URI originalUri = URI.create(request.url()); + String serviceId = originalUri.getHost(); + Assert.state(serviceId != null, + "Request URI does not contain a valid hostname: " + originalUri); + ServiceInstance instance = loadBalancerClient.choose(serviceId); + if (instance == null) { + String message = "Load balancer does not contain an instance for the service " + + serviceId; + if (LOG.isWarnEnabled()) { + LOG.warn(message); + } + return Response.builder().request(request) + .status(HttpStatus.SERVICE_UNAVAILABLE.value()) + .body(message, StandardCharsets.UTF_8).build(); + } + String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri) + .toString(); + Request newRequest = Request.create(request.httpMethod(), reconstructedUrl, + enrichRequstHeader(request.headers()), request.requestBody()); + + return delegate.execute(newRequest, options); + } + + private Map> enrichRequstHeader( + Map> headers) { + String xid = RootContext.getXID(); + if (!StringUtils.isEmpty(xid)) { + Map> newHeaders = new HashMap<>(); + newHeaders.putAll(headers); + newHeaders.put(RootContext.KEY_XID, Arrays.asList(xid)); + return newHeaders; + } + return headers; + } + +} diff --git a/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java b/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java index 95c2a3f8..58b9ef2c 100644 --- a/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java +++ b/spring-cloud-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java @@ -16,9 +16,14 @@ package com.alibaba.cloud.seata.feign; +import java.lang.reflect.Field; + import feign.Client; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; @@ -28,12 +33,16 @@ import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; */ public class SeataFeignObjectWrapper { + private static final Log LOG = LogFactory.getLog(SeataFeignObjectWrapper.class); + private final BeanFactory beanFactory; private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory; private SpringClientFactory springClientFactory; + private BlockingLoadBalancerClient loadBalancerClient; + SeataFeignObjectWrapper(BeanFactory beanFactory) { this.beanFactory = beanFactory; } @@ -45,11 +54,41 @@ public class SeataFeignObjectWrapper { return new SeataLoadBalancerFeignClient(client.getDelegate(), factory(), clientFactory(), this.beanFactory); } + if (bean.getClass().getName().equals( + "org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient")) { + return new SeataFeignBlockingLoadBalancerClient(getClient(bean), + loadBalancerClient()); + } return new SeataFeignClient(this.beanFactory, (Client) bean); } return bean; } + private Client getClient(Object bean) { + Field client = null; + boolean oldAccessible = false; + try { + client = bean.getClass().getDeclaredField("delegate"); + oldAccessible = client.isAccessible(); + client.setAccessible(true); + return (Client) client.get(bean); + } + catch (Exception e) { + LOG.error("get delegate client error", e); + } + finally { + client.setAccessible(oldAccessible); + } + return null; + } + + private BlockingLoadBalancerClient loadBalancerClient() { + if (this.loadBalancerClient != null) { + return this.loadBalancerClient; + } + return beanFactory.getBean(BlockingLoadBalancerClient.class); + } + CachingSpringLoadBalancerFactory factory() { if (this.cachingSpringLoadBalancerFactory == null) { this.cachingSpringLoadBalancerFactory = this.beanFactory From 0519e551ff0d3ae4abea37bd66ca878870766888 Mon Sep 17 00:00:00 2001 From: 631359746 <631359746@qq.com> Date: Fri, 6 Dec 2019 11:31:57 +0800 Subject: [PATCH 4/4] Update SentinelSCGAutoConfiguration.java correct the log print wrong content --- .../sentinel/gateway/scg/SentinelSCGAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java index cd397158..386b7d1b 100644 --- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java @@ -120,7 +120,7 @@ public class SentinelSCGAutoConfiguration { "[Sentinel SpringCloudGateway] using AnonymousBlockRequestHandler, responseStatus: " + fallbackProperties.getResponseStatus() + ", responseBody: " - + fallbackProperties.getResponseStatus()); + + fallbackProperties.getResponseBody()); } } String redirectUrl = fallbackProperties.getRedirect();