From 0b50a47a02244ac3a0dc8db650169866a3a81c45 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Fri, 10 Jan 2020 20:11:26 +0800 Subject: [PATCH 1/8] enhance load config data from Nacos --- .../nacos/NacosConfigAutoConfiguration.java | 3 +- .../client/NacosPropertySourceBuilder.java | 13 +--- .../nacos/parser/AbstractNacosDataParser.java | 10 +-- .../nacos/parser/NacosDataJsonParser.java | 70 +++++++++++-------- .../nacos/parser/NacosDataXmlParser.java | 10 +-- 5 files changed, 52 insertions(+), 54 deletions(-) diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java index e851faef5..60075c9c1 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java @@ -64,7 +64,8 @@ public class NacosConfigAutoConfiguration { public NacosContextRefresher nacosContextRefresher( NacosConfigManager nacosConfigManager, NacosRefreshHistory nacosRefreshHistory) { - // Consider that it is not necessary to be compatible with the previous configuration + // Consider that it is not necessary to be compatible with the previous + // configuration // and use the new configuration if necessary. return new NacosContextRefresher(nacosConfigManager, nacosRefreshHistory); } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java index 3f650b5e8..767a72c1e 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java @@ -17,7 +17,6 @@ package com.alibaba.cloud.nacos.client; import java.util.Date; -import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -111,17 +110,7 @@ public class NacosPropertySourceBuilder { @SuppressWarnings("unchecked") private Map propertiesToMap(Properties properties) { Map result = new HashMap<>(16); - Enumeration keys = (Enumeration) properties.propertyNames(); - while (keys.hasMoreElements()) { - String key = keys.nextElement(); - String value = properties.getProperty(key); - if (value != null) { - result.put(key, value.trim()); - } - else { - result.put(key, null); - } - } + properties.forEach((k, v) -> result.put(String.valueOf(k), v)); return result; } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java index 388961181..4109b049a 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java @@ -111,12 +111,12 @@ public abstract class AbstractNacosDataParser { /** * Generate key-value pairs from the map. */ - protected Properties generateProperties(Map map) { + protected Properties generateProperties(Map map) { if (null == map || map.isEmpty()) { return null; } Properties properties = new Properties(); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); if (StringUtils.isEmpty(key)) { continue; @@ -130,12 +130,12 @@ public abstract class AbstractNacosDataParser { /** * Reload the key ending in `value` if need. */ - protected Map reloadMap(Map map) { + protected Map reloadMap(Map map) { if (map == null || map.isEmpty()) { return null; } - Map result = new HashMap<>(map); - for (Map.Entry entry : map.entrySet()) { + Map result = new HashMap<>(map); + for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); if (key.contains(DOT)) { int idx = key.lastIndexOf(DOT); diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java index 437661a39..7b22192d1 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java @@ -17,18 +17,22 @@ package com.alibaba.cloud.nacos.parser; import java.io.IOException; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; +import java.util.Set; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** * @author zkz + * @author yuhuangbin */ public class NacosDataJsonParser extends AbstractNacosDataParser { @@ -41,7 +45,7 @@ public class NacosDataJsonParser extends AbstractNacosDataParser { if (StringUtils.isEmpty(data)) { return null; } - Map map = parseJSON2Map(data); + Map map = parseJSON2Map(data); return this.generateProperties(this.reloadMap(map)); } @@ -51,44 +55,48 @@ public class NacosDataJsonParser extends AbstractNacosDataParser { * @return the map convert by json string * @throws IOException thrown if there is a problem parsing config. */ - public static Map parseJSON2Map(String json) throws IOException { - Map map = new HashMap<>(32); + public static Map parseJSON2Map(String json) throws IOException { + Map result = new HashMap<>(32); + ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = mapper.readTree(json); - if (null == jsonNode) { - return map; + Map nacosDataMap = mapper.readValue(json, Map.class); + + if (CollectionUtils.isEmpty(nacosDataMap)) { + return result; } - parseJsonNode(map, jsonNode, ""); - return map; + parseNacosDataMap(result, nacosDataMap, ""); + return result; } - private static void parseJsonNode(Map jsonMap, JsonNode jsonNode, - String parentKey) { - Iterator fieldNames = jsonNode.fieldNames(); - while (fieldNames.hasNext()) { - String name = fieldNames.next(); - String fullKey = StringUtils.isEmpty(parentKey) ? name - : parentKey + DOT + name; - JsonNode resultValue = jsonNode.findValue(name); - if (null == resultValue) { + private static void parseNacosDataMap(Map result, + Map dataMap, String parentKey) { + Set> entries = dataMap.entrySet(); + for (Iterator> iterator = entries.iterator(); iterator + .hasNext();) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + Object value = entry.getValue(); + + String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[") + ? parentKey.concat(key) : parentKey.concat(DOT).concat(key); + + if (value instanceof Map) { + Map map = (Map) value; + parseNacosDataMap(result, map, fullKey); continue; } - if (resultValue.isArray()) { - Iterator iterator = resultValue.elements(); - while (iterator != null && iterator.hasNext()) { - JsonNode next = iterator.next(); - if (null == next) { - continue; - } - parseJsonNode(jsonMap, next, fullKey); + else if (value instanceof Collection) { + int count = 0; + Collection collection = (Collection) value; + for (Object object : collection) { + parseNacosDataMap(result, + Collections.singletonMap("[" + (count++) + "]", object), + fullKey); } continue; } - if (resultValue.isObject()) { - parseJsonNode(jsonMap, resultValue, fullKey); - continue; - } - jsonMap.put(fullKey, resultValue.asText()); + + result.put(fullKey, value); } } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java index 8a43ad9cf..7a9c45d60 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java @@ -50,13 +50,13 @@ public class NacosDataXmlParser extends AbstractNacosDataParser { if (StringUtils.isEmpty(data)) { return null; } - Map map = parseXml2Map(data); + Map map = parseXml2Map(data); return this.generateProperties(this.reloadMap(map)); } - private Map parseXml2Map(String xml) throws IOException { + private Map parseXml2Map(String xml) throws IOException { xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", ""); - Map map = new HashMap<>(32); + Map map = new HashMap<>(32); try { DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); @@ -73,7 +73,7 @@ public class NacosDataXmlParser extends AbstractNacosDataParser { return map; } - private void parseNodeList(NodeList nodeList, Map map, + private void parseNodeList(NodeList nodeList, Map map, String parentKey) { if (nodeList == null || nodeList.getLength() < 1) { return; @@ -104,7 +104,7 @@ public class NacosDataXmlParser extends AbstractNacosDataParser { } } - private void parseNodeAttr(NamedNodeMap nodeMap, Map map, + private void parseNodeAttr(NamedNodeMap nodeMap, Map map, String parentKey) { if (null == nodeMap || nodeMap.getLength() < 1) { return; From f7455bcf88d4c9e8731ae1f9fc62b484ea7627e4 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Mon, 13 Jan 2020 10:44:15 +0800 Subject: [PATCH 2/8] add Json parser test cast --- .../nacos/NacosConfigurationXmlJsonTest.java | 76 ++++++++++++++----- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/spring-cloud-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java b/spring-cloud-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java index da1380c2f..b06cfd862 100644 --- a/spring-cloud-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java +++ b/spring-cloud-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java @@ -39,6 +39,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -51,24 +52,23 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @PowerMockIgnore("javax.management.*") @PowerMockRunnerDelegate(SpringRunner.class) @PrepareForTest({ NacosConfigService.class }) -@SpringBootTest(classes = NacosConfigurationXmlJsonTest.TestConfig.class, - properties = { "spring.application.name=xmlApp", "spring.profiles.active=dev", - "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.config.namespace=test-namespace", - "spring.cloud.nacos.config.encode=utf-8", - "spring.cloud.nacos.config.timeout=1000", - "spring.cloud.nacos.config.group=test-group", - "spring.cloud.nacos.config.name=test-name", - "spring.cloud.nacos.config.cluster-name=test-cluster", - "spring.cloud.nacos.config.file-extension=xml", - "spring.cloud.nacos.config.contextPath=test-contextpath", - "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", - "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", - "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", - "spring.cloud.nacos.config.shared-dataids=shared-data1.properties", - "spring.cloud.nacos.config.accessKey=test-accessKey", - "spring.cloud.nacos.config.secretKey=test-secretKey" }, - webEnvironment = NONE) +@SpringBootTest(classes = NacosConfigurationXmlJsonTest.TestConfig.class, properties = { + "spring.application.name=xmlApp", "spring.profiles.active=dev", + "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.config.namespace=test-namespace", + "spring.cloud.nacos.config.encode=utf-8", + "spring.cloud.nacos.config.timeout=1000", + "spring.cloud.nacos.config.group=test-group", + "spring.cloud.nacos.config.name=test-name", + "spring.cloud.nacos.config.cluster-name=test-cluster", + "spring.cloud.nacos.config.file-extension=xml", + "spring.cloud.nacos.config.contextPath=test-contextpath", + "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", + "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", + "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", + "spring.cloud.nacos.config.shared-dataids=shared-data1.properties,shared-data.json", + "spring.cloud.nacos.config.accessKey=test-accessKey", + "spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE) public class NacosConfigurationXmlJsonTest { static { @@ -136,6 +136,22 @@ public class NacosConfigurationXmlJsonTest { return "shared-name=shared-value-1"; } + if ("shared-data.json".equals(args[0]) + && "DEFAULT_GROUP".equals(args[1])) { + return "{\n" + " \"test\" : {\n" + + " \"name\" : \"test\",\n" + + " \"list\" : [\n" + " {\n" + + " \"name\" :\"listname1\",\n" + + " \"age\":1\n" + " },\n" + + " {\n" + + " \"name\" :\"listname2\",\n" + + " \"age\":2\n" + " }\n" + + " ],\n" + " \"metadata\" : {\n" + + " \"intKey\" : 123,\n" + + " \"booleanKey\" : true\n" + " }\n" + + " }\n" + "}"; + } + return ""; } }); @@ -156,6 +172,9 @@ public class NacosConfigurationXmlJsonTest { @Autowired private NacosRefreshHistory refreshHistory; + @Autowired + private Environment environment; + @Test public void contextLoads() throws Exception { @@ -176,6 +195,27 @@ public class NacosConfigurationXmlJsonTest { checkoutEndpoint(); + checkJsonParser(); + } + + private void checkJsonParser() { + assertThat(environment.getProperty("test.name", String.class)).isEqualTo("test"); + + assertThat(environment.getProperty("test.list[0].name", String.class)) + .isEqualTo("listname1"); + assertThat(environment.getProperty("test.list[0].age", Integer.class)) + .isEqualTo(1); + + assertThat(environment.getProperty("test.list[1].name", String.class)) + .isEqualTo("listname2"); + assertThat(environment.getProperty("test.list[1].age", Integer.class)) + .isEqualTo(2); + + assertThat( + (Integer) environment.getProperty("test.metadata.intKey", Object.class)) + .isEqualTo(123); + assertThat((Boolean) environment.getProperty("test.metadata.booleanKey", + Object.class)).isEqualTo(true); } private void checkoutNacosConfigServerAddr() { From a9e519265a9009f965146e545d4e12eff59d71c3 Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Mon, 13 Jan 2020 11:28:23 +0800 Subject: [PATCH 3/8] add s-c-loadbalancer example --- .../pom.xml | 74 +++++++++ .../scripts/openfeign.sh | 7 + .../scripts/resttemplate.sh | 7 + .../examples/ConsumerSCLBApplication.java | 152 ++++++++++++++++++ .../examples/MyLoadBalancerConfiguration.java | 44 +++++ .../src/main/resources/application.properties | 6 + .../cloud/examples/ProviderApplication.java | 2 +- .../nacos-discovery-example/pom.xml | 1 + 8 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/pom.xml create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/openfeign.sh create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/resttemplate.sh create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/pom.xml new file mode 100644 index 000000000..dc211efeb --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/pom.xml @@ -0,0 +1,74 @@ + + + + + com.alibaba.cloud + nacos-discovery-example + 2.2.0.BUILD-SNAPSHOT + + 4.0.0 + + + nacos-discovery-consumer-sclb-example + jar + Example demonstrating how to use nacos discovery + + + + + org.springframework.boot + spring-boot-starter-web + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + true + + + + + + diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/openfeign.sh b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/openfeign.sh new file mode 100644 index 000000000..975d060d0 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/openfeign.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +n=1 +while [ $n -le 10 ] +do + echo `curl -s http://localhost:18083/echo-feign/openfeign` + let n++ +done diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/resttemplate.sh b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/resttemplate.sh new file mode 100644 index 000000000..e9d2e6300 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/scripts/resttemplate.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +n=1 +while [ $n -le 10 ] +do + echo `curl -s http://localhost:18083/echo-rest/resttemplate` + let n++ +done diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java new file mode 100644 index 000000000..695538af7 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.examples; + +import java.util.List; +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.client.loadbalancer.reactive.DefaultResponse; +import org.springframework.cloud.client.loadbalancer.reactive.EmptyResponse; +import org.springframework.cloud.client.loadbalancer.reactive.Request; +import org.springframework.cloud.client.loadbalancer.reactive.Response; +import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; +import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier; +import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +/** + * @author Jim + */ +@SpringBootApplication +@EnableDiscoveryClient(autoRegister = false) +@EnableFeignClients +public class ConsumerSCLBApplication { + + @LoadBalanced + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Configuration + @LoadBalancerClient(value = "service-provider", configuration = MyLoadBalancerConfiguration.class) + class MySCLBConfiguration { + + } + + static class RandomLoadBalancer implements ReactorServiceInstanceLoadBalancer { + + private static final Logger log = LoggerFactory + .getLogger(RandomLoadBalancer.class); + + private ObjectProvider serviceInstanceListSupplierProvider; + + private final String serviceId; + + private final Random random; + + public RandomLoadBalancer( + ObjectProvider serviceInstanceListSupplierProvider, + String serviceId) { + this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider; + this.serviceId = serviceId; + this.random = new Random(); + } + + @Override + public Mono> choose(Request request) { + log.info("random spring cloud loadbalacer active -.-"); + ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider + .getIfAvailable(NoopServiceInstanceListSupplier::new); + return supplier.get().next().map(this::getInstanceResponse); + } + + private Response getInstanceResponse( + List instances) { + if (instances.isEmpty()) { + return new EmptyResponse(); + } + ServiceInstance instance = instances.get(random.nextInt(instances.size())); + + return new DefaultResponse(instance); + } + } + + @FeignClient(name = "service-provider") + public interface EchoService { + + @GetMapping("/echo/{str}") + String echo(@PathVariable("str") String str); + + @GetMapping("/divide") + String divide(@RequestParam("a") Integer a, @RequestParam("b") Integer b); + + default String divide(Integer a) { + return divide(a, 0); + } + + @GetMapping("/notFound") + String notFound(); + + } + + @RestController + class TestController { + @Autowired + private RestTemplate restTemplate; + + @Autowired + private EchoService echoService; + + @GetMapping("/echo-rest/{str}") + public String rest(@PathVariable String str) { + return restTemplate.getForObject("http://service-provider/echo/" + str, + String.class); + } + + @GetMapping("/echo-feign/{str}") + public String feign(@PathVariable String str) { + return echoService.echo(str); + } + + } + + public static void main(String[] args) { + SpringApplication.run(ConsumerSCLBApplication.class, args); + } + +} diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java new file mode 100644 index 000000000..cad930ddd --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.examples; + +import com.alibaba.cloud.examples.ConsumerSCLBApplication.RandomLoadBalancer; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; + +/** + * @author Jim + */ +public class MyLoadBalancerConfiguration { + + @Bean + @ConditionalOnMissingBean + public ReactorLoadBalancer reactorServiceInstanceLoadBalancer( + Environment environment, + LoadBalancerClientFactory loadBalancerClientFactory) { + String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); + return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, + ServiceInstanceListSupplier.class), name); + } + +} diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties new file mode 100644 index 000000000..2c021065c --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.application.name=service-consumer-sclb +server.port=18083 +management.endpoints.web.exposure.include=* +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 + +spring.cloud.loadbalancer.ribbon.enabled=false \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java index 64b43b233..94a842598 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java @@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.RestController; /** * @author xiaojing */ -@EnableDiscoveryClient(autoRegister = false) +@EnableDiscoveryClient @SpringBootApplication public class ProviderApplication { diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml index 3c5c31fa2..6518e4cd0 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml @@ -18,6 +18,7 @@ nacos-discovery-consumer-example + nacos-discovery-consumer-sclb-example nacos-discovery-provider-example nacos-discovery-spring-cloud-config-server-example nacos-discovery-spring-cloud-config-client-example From b70129c17f4ae854388ec6768c2696c2afa958d5 Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Mon, 13 Jan 2020 20:14:23 +0800 Subject: [PATCH 4/8] add reactive discovery example --- .../pom.xml | 63 ++++++++++++++++ .../examples/ConsumerReactiveApplication.java | 72 +++++++++++++++++++ .../src/main/resources/application.properties | 6 ++ .../nacos-discovery-example/pom.xml | 1 + 4 files changed, 142 insertions(+) create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java create mode 100644 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml new file mode 100644 index 000000000..704879687 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml @@ -0,0 +1,63 @@ + + + + + com.alibaba.cloud + nacos-discovery-example + 2.2.0.BUILD-SNAPSHOT + + 4.0.0 + + + nacos-reactivediscovery-consumer-example + jar + Example demonstrating how to use nacos discovery + + + + + org.springframework.boot + spring-boot-starter-webflux + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + true + + + + + + diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java new file mode 100644 index 000000000..7da82f789 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.examples; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * @author Jim + */ +@SpringBootApplication +public class ConsumerReactiveApplication { + + @Bean + @LoadBalanced + public WebClient.Builder webClient() { + return WebClient.builder(); + } + + @RestController + class MyController { + @Autowired + private ReactiveDiscoveryClient reactiveDiscoveryClient; + + @Autowired + private WebClient.Builder webClientBuilder; + + @GetMapping("/all-services") + public Flux allServices() { + return reactiveDiscoveryClient.getInstances("service-provider") + .map(serviceInstance -> serviceInstance.getHost() + ":" + + serviceInstance.getPort()); + } + + @GetMapping("/service-call/{name}") + public Mono serviceCall(@PathVariable("name") String name) { + return webClientBuilder.build().get() + .uri("http://service-provider/echo/" + name).retrieve() + .bodyToMono(String.class); + } + } + + public static void main(String[] args) { + SpringApplication.run(ConsumerReactiveApplication.class, args); + } + +} diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties new file mode 100644 index 000000000..a96e890a1 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.application.name=service-consumer-reactive +server.port=18083 +management.endpoints.web.exposure.include=* +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 + +spring.cloud.loadbalancer.ribbon.enabled=false \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml index 6518e4cd0..a0be8ef00 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml @@ -19,6 +19,7 @@ nacos-discovery-consumer-example nacos-discovery-consumer-sclb-example + nacos-reactivediscovery-consumer-example nacos-discovery-provider-example nacos-discovery-spring-cloud-config-server-example nacos-discovery-spring-cloud-config-client-example From b0273fb1c8d8c60370b912a80594c50e5da7a3f4 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Sun, 12 Jan 2020 16:40:35 +0800 Subject: [PATCH 5/8] upgrade sentinel version and enhance --- spring-cloud-alibaba-dependencies/pom.xml | 7 +- .../sentinel-core-example/pom.xml | 4 + .../cloud/examples/WebMvcConfiguration.java | 36 ++++++++ .../src/main/resources/application.properties | 3 + .../main/resources/templates/errorPage.html | 10 ++ spring-cloud-alibaba-sentinel/pom.xml | 10 +- .../cloud/sentinel/SentinelConstants.java | 20 ++++ .../cloud/sentinel/SentinelProperties.java | 40 ++++++-- .../SentinelWebAutoConfiguration.java | 92 +++++++++++-------- .../custom/SentinelAutoConfiguration.java | 8 +- .../sentinel/endpoint/SentinelEndpoint.java | 5 +- ...itional-spring-configuration-metadata.json | 11 ++- .../SentinelAutoConfigurationTests.java | 19 +--- .../sentinel/SentinelBeanAutowiredTests.java | 40 ++++---- 14 files changed, 205 insertions(+), 100 deletions(-) create mode 100644 spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/WebMvcConfiguration.java create mode 100644 spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/templates/errorPage.html diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 564672510..a6df08172 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -18,7 +18,7 @@ Spring Cloud Alibaba Dependencies - 1.6.3 + 1.7.1 3.1.0 0.9.0 1.1.4 @@ -198,6 +198,11 @@ sentinel-api-gateway-adapter-common ${sentinel.version} + + com.alibaba.csp + sentinel-spring-webmvc-adapter + ${sentinel.version} + diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml index 3b7c0ce60..2db02dc2a 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml @@ -30,6 +30,10 @@ org.springframework.boot spring-boot-starter-actuator + + org.springframework.boot + spring-boot-starter-thymeleaf + diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/WebMvcConfiguration.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/WebMvcConfiguration.java new file mode 100644 index 000000000..b4a562fbe --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/WebMvcConfiguration.java @@ -0,0 +1,36 @@ +/* + * 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.examples; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author yuhuangbin + */ +@Configuration +@EnableWebMvc +public class WebMvcConfiguration implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/errorPage").setViewName("errorPage"); + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index 4a60ba53b..16ee4a26a 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -9,6 +9,9 @@ management.health.diskspace.enabled=false spring.cloud.sentinel.transport.dashboard=localhost:8080 spring.cloud.sentinel.eager=true + +#spring.cloud.sentinel.block-page=/errorPage +#spring.cloud.sentinel.filter.enabled=false #spring.cloud.sentinel.http-method-specify=false spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/templates/errorPage.html b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/templates/errorPage.html new file mode 100644 index 000000000..04211d7e0 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/templates/errorPage.html @@ -0,0 +1,10 @@ + + + + + Title + + +This is error page. + + \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index 29c659841..09cb5e8d7 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -41,11 +41,6 @@ true - - com.alibaba.csp - sentinel-web-servlet - - org.springframework.boot spring-boot-starter-web @@ -57,6 +52,11 @@ sentinel-spring-webflux-adapter + + com.alibaba.csp + sentinel-spring-webmvc-adapter + + org.springframework.boot spring-boot-starter-webflux diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelConstants.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelConstants.java index ca008a047..dd6b3dc6d 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelConstants.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelConstants.java @@ -26,6 +26,11 @@ public final class SentinelConstants { */ public static final String PROPERTY_PREFIX = "spring.cloud.sentinel"; + /** + * Block page key. + */ + public static final String BLOCK_PAGE_URL_CONF_KEY = "csp.sentinel.web.servlet.block.page"; + /** * Block type. */ @@ -41,6 +46,21 @@ public final class SentinelConstants { */ public static final String URLCLEANER_TYPE = "urlCleaner"; + /** + * The cold factor. + */ + public static final String COLD_FACTOR = "3"; + + /** + * The charset. + */ + public static final String CHARSET = "UTF-8"; + + /** + * The Sentinel api port. + */ + public static final String API_PORT = "8719"; + private SentinelConstants() { throw new AssertionError("Must not instantiate constant utility class"); } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java index 8bef50ad1..22d1aff28 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.sentinel; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -26,7 +27,9 @@ 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.DeprecatedConfigurationProperty; import org.springframework.core.Ordered; +import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; /** @@ -52,6 +55,11 @@ public class SentinelProperties { */ private boolean enabled = true; + /** + * The process page when the flow control is triggered. + */ + private String blockPage; + /** * Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'. */ @@ -75,7 +83,7 @@ public class SentinelProperties { private Servlet servlet = new Servlet(); /** - * Sentinel filter when the application is web, the configuration is effective. + * Sentinel interceptor when the application is web, the configuration is effective. */ private Filter filter = new Filter(); @@ -174,12 +182,23 @@ public class SentinelProperties { this.httpMethodSpecify = httpMethodSpecify; } + public String getBlockPage() { + if (StringUtils.hasText(this.blockPage)) { + return this.blockPage; + } + return this.servlet.getBlockPage(); + } + + public void setBlockPage(String blockPage) { + this.blockPage = blockPage; + } + public static class Flow { /** * The cold factor {@link SentinelConfig#COLD_FACTOR}. */ - private String coldFactor = "3"; + private String coldFactor = SentinelConstants.COLD_FACTOR; public String getColdFactor() { return coldFactor; @@ -198,10 +217,15 @@ public class SentinelProperties { */ private String blockPage; + @Deprecated + @DeprecatedConfigurationProperty( + reason = "replaced to SentinelProperties#blockPage.", + replacement = SentinelConstants.PROPERTY_PREFIX + ".block-page") public String getBlockPage() { return blockPage; } + @Deprecated public void setBlockPage(String blockPage) { this.blockPage = blockPage; } @@ -224,7 +248,7 @@ public class SentinelProperties { * Charset when sentinel write or search metric file. * {@link SentinelConfig#CHARSET} */ - private String charset = "UTF-8"; + private String charset = SentinelConstants.CHARSET; public String getFileSingleSize() { return fileSingleSize; @@ -257,7 +281,7 @@ public class SentinelProperties { /** * Sentinel api port, default value is 8719 {@link TransportConfig#SERVER_PORT}. */ - private String port = "8719"; + private String port = SentinelConstants.API_PORT; /** * Sentinel dashboard address, won't try to connect dashboard when address is @@ -314,18 +338,18 @@ public class SentinelProperties { public static class Filter { /** - * Sentinel filter chain order. + * SentinelWebInterceptor order, will be register to InterceptorRegistry. */ private int order = Ordered.HIGHEST_PRECEDENCE; /** - * URL pattern for sentinel filter, default is /*. + * URL pattern for SentinelWebInterceptor, default is /*. */ - private List urlPatterns; + private List urlPatterns = Arrays.asList("/*"); /** * Enable to instance - * {@link com.alibaba.csp.sentinel.adapter.servlet.CommonFilter}. + * {@link com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor}. */ private boolean enabled = true; diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java index 58628310c..b5b28cdfc 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java @@ -16,18 +16,14 @@ package com.alibaba.cloud.sentinel; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; -import javax.annotation.PostConstruct; -import javax.servlet.Filter; - -import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; -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; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,19 +33,22 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author xiaojing + * @author yuhuangbin */ @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) -@ConditionalOnClass(CommonFilter.class) @ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true) +@ConditionalOnClass(SentinelWebInterceptor.class) @EnableConfigurationProperties(SentinelProperties.class) -public class SentinelWebAutoConfiguration { +public class SentinelWebAutoConfiguration implements WebMvcConfigurer { private static final Logger log = LoggerFactory .getLogger(SentinelWebAutoConfiguration.class); @@ -61,44 +60,61 @@ public class SentinelWebAutoConfiguration { private Optional urlCleanerOptional; @Autowired - private Optional urlBlockHandlerOptional; + private Optional blockExceptionHandlerOptional; @Autowired private Optional requestOriginParserOptional; - @PostConstruct - public void init() { - urlBlockHandlerOptional.ifPresent(WebCallbackManager::setUrlBlockHandler); - urlCleanerOptional.ifPresent(WebCallbackManager::setUrlCleaner); - requestOriginParserOptional.ifPresent(WebCallbackManager::setRequestOriginParser); + @Autowired + private Optional sentinelWebInterceptorOptional; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + if (!sentinelWebInterceptorOptional.isPresent()) { + return; + } + SentinelProperties.Filter filterConfig = properties.getFilter(); + registry.addInterceptor(sentinelWebInterceptorOptional.get()) + .order(filterConfig.getOrder()) + .addPathPatterns(filterConfig.getUrlPatterns()); + log.info( + "[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", + filterConfig.getUrlPatterns()); } @Bean @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) - public FilterRegistrationBean sentinelFilter() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); + public SentinelWebInterceptor sentinelWebInterceptor( + SentinelWebMvcConfig sentinelWebMvcConfig) { + return new SentinelWebInterceptor(sentinelWebMvcConfig); + } - SentinelProperties.Filter filterConfig = properties.getFilter(); + @Bean + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) + public SentinelWebMvcConfig sentinelWebMvcConfig() { + SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig(); + sentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify()); - if (filterConfig.getUrlPatterns() == null - || filterConfig.getUrlPatterns().isEmpty()) { - List defaultPatterns = new ArrayList<>(); - defaultPatterns.add("/*"); - filterConfig.setUrlPatterns(defaultPatterns); + if (blockExceptionHandlerOptional.isPresent()) { + blockExceptionHandlerOptional + .ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler); + } + else { + if (StringUtils.hasText(properties.getBlockPage())) { + sentinelWebMvcConfig.setBlockExceptionHandler(((request, response, + e) -> response.sendRedirect(properties.getBlockPage()))); + } + else { + sentinelWebMvcConfig + .setBlockExceptionHandler(new DefaultBlockExceptionHandler()); + } } - registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0])); - Filter filter = new CommonFilter(); - registration.setFilter(filter); - registration.setOrder(filterConfig.getOrder()); - registration.addInitParameter("HTTP_METHOD_SPECIFY", - String.valueOf(properties.getHttpMethodSpecify())); - log.info( - "[Sentinel Starter] register Sentinel CommonFilter with urlPatterns: {}.", - filterConfig.getUrlPatterns()); - return registration; - + urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner); + requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser); + return sentinelWebMvcConfig; } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java index 7eea97fff..b71d94835 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java @@ -21,7 +21,6 @@ import javax.annotation.PostConstruct; import com.alibaba.cloud.sentinel.SentinelProperties; import com.alibaba.cloud.sentinel.datasource.converter.JsonConverter; import com.alibaba.cloud.sentinel.datasource.converter.XmlConverter; -import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; import com.alibaba.csp.sentinel.config.SentinelConfig; import com.alibaba.csp.sentinel.init.InitExecutor; @@ -50,6 +49,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.util.StringUtils; +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; +import static com.alibaba.csp.sentinel.config.SentinelConfig.setConfig; + /** * @author xiaojing * @author jiashuai.xie @@ -124,8 +126,8 @@ public class SentinelAutoConfiguration { System.setProperty(SentinelConfig.COLD_FACTOR, properties.getFlow().getColdFactor()); } - if (StringUtils.hasText(properties.getServlet().getBlockPage())) { - WebServletConfig.setBlockPage(properties.getServlet().getBlockPage()); + if (StringUtils.hasText(properties.getBlockPage())) { + setConfig(BLOCK_PAGE_URL_CONF_KEY, properties.getBlockPage()); } // earlier initialize diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpoint.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpoint.java index 98aace362..c1f38a850 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpoint.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpoint.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Map; import com.alibaba.cloud.sentinel.SentinelProperties; -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; @@ -34,6 +33,8 @@ import com.alibaba.csp.sentinel.util.AppNameUtil; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; + /** * Endpoint for Sentinel, contains ans properties and rules. * @@ -56,7 +57,7 @@ public class SentinelEndpoint { result.put("appName", AppNameUtil.getAppName()); result.put("logDir", LogBase.getLogBaseDir()); result.put("logUsePid", LogBase.isLogNameUsePid()); - result.put("blockPage", WebServletConfig.getBlockPage()); + result.put("blockPage", SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY)); result.put("metricsFileSize", SentinelConfig.singleMetricFileSize()); result.put("metricsFileCharset", SentinelConfig.charset()); result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount()); diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json index ec4c63d7a..93acd7e52 100644 --- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -43,13 +43,13 @@ "name": "spring.cloud.sentinel.filter.order", "type": "java.lang.Integer", "defaultValue": "Integer.MIN_VALUE", - "description": "sentinel filter chain order, will be set to FilterRegistrationBean." + "description": "SentinelWebInterceptor order, will be register to InterceptorRegistry." }, { "name": "spring.cloud.sentinel.filter.enabled", "type": "java.lang.Boolean", "defaultValue": true, - "description": "Enable to instance com.alibaba.csp.sentinel.adapter.servlet.CommonFilter." + "description": "Enable to register com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor." }, { "name": "spring.cloud.sentinel.metric.charset", @@ -79,10 +79,15 @@ "description": "log file should with pid." }, { - "name": "spring.cloud.sentinel.servlet.blockPage", + "name": "spring.cloud.sentinel.block-page", "type": "java.lang.String", "description": "the process page when the flow control is triggered." }, + { + "name": "spring.cloud.sentinel.servlet.block-page", + "type": "java.lang.String", + "description": "recommoned use spring.cloud.sentinel.block-page." + }, { "name": "spring.cloud.sentinel.flow.coldFactor", "type": "java.lang.String", diff --git a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java index 045ab8b74..ae67bd383 100644 --- a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java @@ -24,7 +24,6 @@ import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration; import com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor; import com.alibaba.cloud.sentinel.endpoint.SentinelEndpoint; import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse; -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.BlockException; @@ -43,7 +42,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpRequest; @@ -55,6 +53,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; @@ -70,7 +69,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen "spring.cloud.sentinel.filter.urlPatterns=/*,/test", "spring.cloud.sentinel.metric.fileSingleSize=9999", "spring.cloud.sentinel.metric.fileTotalCount=100", - "spring.cloud.sentinel.servlet.blockPage=/error", + "spring.cloud.sentinel.blockPage=/error", "spring.cloud.sentinel.flow.coldFactor=3", "spring.cloud.sentinel.eager=true", "spring.cloud.sentinel.log.switchPid=true", @@ -84,9 +83,6 @@ public class SentinelAutoConfigurationTests { @Autowired private SentinelProperties sentinelProperties; - @Autowired - private FilterRegistrationBean filterRegistrationBean; - @Autowired private SentinelBeanPostProcessor sentinelBeanPostProcessor; @@ -130,9 +126,6 @@ public class SentinelAutoConfigurationTests { @Test public void contextLoads() throws Exception { - - assertThat(filterRegistrationBean).isNotNull(); - assertThat(filterRegistrationBean).isNotNull(); assertThat(sentinelBeanPostProcessor).isNotNull(); checkSentinelLog(); @@ -195,12 +188,6 @@ public class SentinelAutoConfigurationTests { assertThat(sentinelProperties.getLog().isSwitchPid()).isEqualTo(true); } - @Test - public void testFilter() { - assertThat(123).isEqualTo(filterRegistrationBean.getOrder()); - assertThat(2).isEqualTo(filterRegistrationBean.getUrlPatterns().size()); - } - @Test public void testSentinelSystemProperties() { assertThat(LogBase.isLogNameUsePid()).isEqualTo(true); @@ -212,7 +199,7 @@ public class SentinelAutoConfigurationTests { assertThat(SentinelConfig.singleMetricFileSize()).isEqualTo(9999); assertThat(SentinelConfig.totalMetricFileCount()).isEqualTo(100); assertThat(SentinelConfig.charset()).isEqualTo("UTF-8"); - assertThat(WebServletConfig.getBlockPage()).isEqualTo("/error"); + assertThat(SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY)).isEqualTo("/error"); } @Test diff --git a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelBeanAutowiredTests.java b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelBeanAutowiredTests.java index cfb671148..a971b52f3 100644 --- a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelBeanAutowiredTests.java +++ b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelBeanAutowiredTests.java @@ -16,18 +16,14 @@ package com.alibaba.cloud.sentinel; -import java.io.IOException; - import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration; -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; -import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil; -import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig; import org.junit.Test; import org.junit.runner.RunWith; @@ -53,7 +49,7 @@ public class SentinelBeanAutowiredTests { private UrlCleaner urlCleaner; @Autowired - private UrlBlockHandler urlBlockHandler; + private BlockExceptionHandler blockExceptionHandler; @Autowired private RequestOriginParser requestOriginParser; @@ -61,10 +57,13 @@ public class SentinelBeanAutowiredTests { @Autowired private SentinelProperties sentinelProperties; + @Autowired + private SentinelWebMvcConfig sentinelWebMvcConfig; + @Test public void contextLoads() throws Exception { assertThat(urlCleaner).isNotNull(); - assertThat(urlBlockHandler).isNotNull(); + assertThat(blockExceptionHandler).isNotNull(); assertThat(requestOriginParser).isNotNull(); assertThat(sentinelProperties).isNotNull(); @@ -80,10 +79,10 @@ public class SentinelBeanAutowiredTests { @Test public void testBeanAutowired() { - assertThat(WebCallbackManager.getUrlCleaner()).isEqualTo(urlCleaner); - assertThat(WebCallbackManager.getUrlBlockHandler()).isEqualTo(urlBlockHandler); - assertThat(WebCallbackManager.getRequestOriginParser()) - .isEqualTo(requestOriginParser); + assertThat(sentinelWebMvcConfig.getUrlCleaner()).isEqualTo(urlCleaner); + assertThat(sentinelWebMvcConfig.getBlockExceptionHandler()) + .isEqualTo(blockExceptionHandler); + assertThat(sentinelWebMvcConfig.getOriginParser()).isEqualTo(requestOriginParser); } @Configuration @@ -113,15 +112,8 @@ public class SentinelBeanAutowiredTests { } @Bean - public UrlBlockHandler urlBlockHandler() { - return new UrlBlockHandler() { - @Override - public void blocked(HttpServletRequest httpServletRequest, - HttpServletResponse httpServletResponse, BlockException e) - throws IOException { - FilterUtil.blockRequest(httpServletRequest, httpServletResponse); - } - }; + public BlockExceptionHandler blockExceptionHandler() { + return new DefaultBlockExceptionHandler(); } } From ddceb5f3121924c7b658d41c1c5c2681965c5853 Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Tue, 14 Jan 2020 15:06:26 +0800 Subject: [PATCH 6/8] add spring cloud sentinel circuitbreaker demo --- .../cloud/examples/ServiceApplication.java | 22 +++++++++++++++++-- .../cloud/examples/TestController.java | 17 ++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java index 17121bd9c..cda038b74 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java @@ -16,11 +16,18 @@ package com.alibaba.cloud.examples; +import java.util.Collections; + +import com.alibaba.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerFactory; +import com.alibaba.cloud.circuitbreaker.sentinel.SentinelConfigBuilder; import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate; import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @@ -31,8 +38,7 @@ import org.springframework.web.client.RestTemplate; public class ServiceApplication { @Bean - @SentinelRestTemplate(blockHandler = "handleException", - blockHandlerClass = ExceptionUtil.class) + @SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class) public RestTemplate restTemplate() { return new RestTemplate(); } @@ -47,6 +53,18 @@ public class ServiceApplication { return new JsonFlowRuleListConverter(); } + @Bean + public Customizer defaultConfig() { + return factory -> { + factory.configureDefault( + id -> new SentinelConfigBuilder().resourceName(id) + .rules(Collections.singletonList(new DegradeRule(id) + .setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(100) + .setTimeWindow(10))) + .build()); + }; + } + public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args); } diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/TestController.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/TestController.java index 1e7a909d9..ffacf273a 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/TestController.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/TestController.java @@ -19,6 +19,7 @@ package com.alibaba.cloud.examples; import com.alibaba.csp.sentinel.annotation.SentinelResource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @@ -32,6 +33,9 @@ public class TestController { @Autowired private RestTemplate restTemplate; + @Autowired + private CircuitBreakerFactory circuitBreakerFactory; + @GetMapping("/hello") @SentinelResource("resource") public String hello() { @@ -54,4 +58,17 @@ public class TestController { return restTemplate.getForObject("http://www.taobao.com/test", String.class); } + @GetMapping("/slow") + public String slow() { + return circuitBreakerFactory.create("show").run(() -> { + try { + Thread.sleep(1000L); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + return "success"; + }, throwable -> "fallback"); + } + } From 00d449ba23db21e5aecca99d889c3061fd6b1312 Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Tue, 14 Jan 2020 16:54:01 +0800 Subject: [PATCH 7/8] pass code check --- .../examples/ConsumerSCLBApplication.java | 17 +++-- .../examples/MyLoadBalancerConfiguration.java | 2 +- .../src/main/resources/application.properties | 2 +- .../examples/ConsumerReactiveApplication.java | 10 +-- .../src/main/resources/application.properties | 2 +- .../cloud/examples/ServiceApplication.java | 3 +- .../nacos/NacosConfigAutoConfiguration.java | 3 +- .../NacosRibbonClientConfiguration.java | 6 +- ...acosRibbonClientPropertyOverrideTests.java | 65 +++++++++---------- .../binder/rocketmq/RocketMQBinderUtils.java | 3 +- 10 files changed, 59 insertions(+), 54 deletions(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java index 695538af7..d60b21341 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/ConsumerSCLBApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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. @@ -62,8 +62,13 @@ public class ConsumerSCLBApplication { return new RestTemplate(); } + public static void main(String[] args) { + SpringApplication.run(ConsumerSCLBApplication.class, args); + } + @Configuration - @LoadBalancerClient(value = "service-provider", configuration = MyLoadBalancerConfiguration.class) + @LoadBalancerClient(value = "service-provider", + configuration = MyLoadBalancerConfiguration.class) class MySCLBConfiguration { } @@ -79,7 +84,7 @@ public class ConsumerSCLBApplication { private final Random random; - public RandomLoadBalancer( + RandomLoadBalancer( ObjectProvider serviceInstanceListSupplierProvider, String serviceId) { this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider; @@ -104,6 +109,7 @@ public class ConsumerSCLBApplication { return new DefaultResponse(instance); } + } @FeignClient(name = "service-provider") @@ -126,6 +132,7 @@ public class ConsumerSCLBApplication { @RestController class TestController { + @Autowired private RestTemplate restTemplate; @@ -145,8 +152,4 @@ public class ConsumerSCLBApplication { } - public static void main(String[] args) { - SpringApplication.run(ConsumerSCLBApplication.class, args); - } - } diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java index cad930ddd..8ff966575 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/java/com/alibaba/cloud/examples/MyLoadBalancerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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. diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties index 2c021065c..40c2b2f56 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-sclb-example/src/main/resources/application.properties @@ -3,4 +3,4 @@ server.port=18083 management.endpoints.web.exposure.include=* spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 -spring.cloud.loadbalancer.ribbon.enabled=false \ No newline at end of file +spring.cloud.loadbalancer.ribbon.enabled=false diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java index 7da82f789..b9e057372 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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. @@ -42,8 +42,13 @@ public class ConsumerReactiveApplication { return WebClient.builder(); } + public static void main(String[] args) { + SpringApplication.run(ConsumerReactiveApplication.class, args); + } + @RestController class MyController { + @Autowired private ReactiveDiscoveryClient reactiveDiscoveryClient; @@ -63,10 +68,7 @@ public class ConsumerReactiveApplication { .uri("http://service-provider/echo/" + name).retrieve() .bodyToMono(String.class); } - } - public static void main(String[] args) { - SpringApplication.run(ConsumerReactiveApplication.class, args); } } diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties index a96e890a1..cedb93f2d 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties @@ -3,4 +3,4 @@ server.port=18083 management.endpoints.web.exposure.include=* spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 -spring.cloud.loadbalancer.ribbon.enabled=false \ No newline at end of file +spring.cloud.loadbalancer.ribbon.enabled=false diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java index cda038b74..7345f74c0 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/com/alibaba/cloud/examples/ServiceApplication.java @@ -38,7 +38,8 @@ import org.springframework.web.client.RestTemplate; public class ServiceApplication { @Bean - @SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class) + @SentinelRestTemplate(blockHandler = "handleException", + blockHandlerClass = ExceptionUtil.class) public RestTemplate restTemplate() { return new RestTemplate(); } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java index e851faef5..60075c9c1 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigAutoConfiguration.java @@ -64,7 +64,8 @@ public class NacosConfigAutoConfiguration { public NacosContextRefresher nacosContextRefresher( NacosConfigManager nacosConfigManager, NacosRefreshHistory nacosRefreshHistory) { - // Consider that it is not necessary to be compatible with the previous configuration + // Consider that it is not necessary to be compatible with the previous + // configuration // and use the new configuration if necessary. return new NacosContextRefresher(nacosConfigManager, nacosRefreshHistory); } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientConfiguration.java index 38396b707..a6294e875 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientConfiguration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientConfiguration.java @@ -44,9 +44,9 @@ public class NacosRibbonClientConfiguration { public ServerList ribbonServerList(IClientConfig config, NacosDiscoveryProperties nacosDiscoveryProperties) { if (this.propertiesFactory.isSet(ServerList.class, config.getClientName())) { - ServerList serverList = this.propertiesFactory.get(ServerList.class, config, - config.getClientName()); - return serverList; + ServerList serverList = this.propertiesFactory.get(ServerList.class, config, + config.getClientName()); + return serverList; } NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); serverList.initWithNiwsConfig(config); diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java index e7ca294cc..3692414f4 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java @@ -35,50 +35,47 @@ import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; - /** * @author liujunjie */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = - NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, - properties = {"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.discovery.port=18080", - "spring.cloud.nacos.discovery.service=remoteApp", - "localApp.ribbon.NIWSServerListClassName=" - + "com.netflix.loadbalancer.ConfigurationBasedServerList", - "localApp.ribbon.listOfServers=127.0.0.1:19090", - "localApp.ribbon.ServerListRefreshInterval=15000"}) +@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, + properties = { "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.port=18080", + "spring.cloud.nacos.discovery.service=remoteApp", + "localApp.ribbon.NIWSServerListClassName=" + + "com.netflix.loadbalancer.ConfigurationBasedServerList", + "localApp.ribbon.listOfServers=127.0.0.1:19090", + "localApp.ribbon.ServerListRefreshInterval=15000" }) public class NacosRibbonClientPropertyOverrideTests { - @Autowired - private SpringClientFactory factory; + @Autowired + private SpringClientFactory factory; + @Test + public void serverListOverridesToTest() { + ConfigurationBasedServerList.class + .cast(getLoadBalancer("localApp").getServerListImpl()); + } - @Test - public void serverListOverridesToTest() { - ConfigurationBasedServerList.class - .cast(getLoadBalancer("localApp").getServerListImpl()); - } + @Test + public void serverListRemoteTest() { + NacosServerList.class.cast(getLoadBalancer("remoteApp").getServerListImpl()); + } - @Test - public void serverListRemoteTest() { - NacosServerList.class - .cast(getLoadBalancer("remoteApp").getServerListImpl()); - } + @SuppressWarnings("unchecked") + private ZoneAwareLoadBalancer getLoadBalancer(String name) { + return (ZoneAwareLoadBalancer) this.factory.getLoadBalancer(name); + } - @SuppressWarnings("unchecked") - private ZoneAwareLoadBalancer getLoadBalancer(String name) { - return (ZoneAwareLoadBalancer) this.factory.getLoadBalancer(name); - } + @Configuration + @RibbonClients + @EnableAutoConfiguration + @ImportAutoConfiguration({ UtilAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class, + RibbonNacosAutoConfiguration.class, NacosDiscoveryClientConfiguration.class }) + protected static class TestConfiguration { - @Configuration - @RibbonClients - @EnableAutoConfiguration - @ImportAutoConfiguration({UtilAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, - ArchaiusAutoConfiguration.class, RibbonNacosAutoConfiguration.class, - NacosDiscoveryClientConfiguration.class}) - protected static class TestConfiguration { + } - } } diff --git a/spring-cloud-stream-binder-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java b/spring-cloud-stream-binder-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java index 6665ea7bf..c7daff0ef 100644 --- a/spring-cloud-stream-binder-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java +++ b/spring-cloud-stream-binder-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java @@ -42,7 +42,8 @@ public final class RocketMQBinderUtils { result.setNameServer(rocketBinderConfigurationProperties.getNameServer()); } else { - result.setNameServer(Arrays.asList(rocketMQProperties.getNameServer().split(";"))); + result.setNameServer( + Arrays.asList(rocketMQProperties.getNameServer().split(";"))); } if (rocketMQProperties.getProducer() == null || StringUtils.isEmpty(rocketMQProperties.getProducer().getAccessKey())) { From 9a5518d3025471406804bbc632ec999c19220a5b Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Wed, 15 Jan 2020 15:30:41 +0800 Subject: [PATCH 8/8] update nacos config example --- .../alibaba/cloud/examples/Application.java | 69 +++++++++++++++++-- .../src/main/resources/bootstrap.properties | 1 + 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/Application.java b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/Application.java index 35cec8c38..30ef8884b 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/Application.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/java/com/alibaba/cloud/examples/Application.java @@ -18,6 +18,7 @@ package com.alibaba.cloud.examples; import java.io.IOException; import java.io.StringReader; +import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; @@ -30,7 +31,9 @@ import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -45,6 +48,52 @@ public class Application { SpringApplication.run(Application.class, args); } + @Bean + public UserConfig userConfig() { + return new UserConfig(); + } + +} + +@ConfigurationProperties(prefix = "user") +class UserConfig { + + private int age; + + private String name; + + private Map map; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + @Override + public String toString() { + return "UserConfig{" + "age=" + age + ", name='" + name + '\'' + ", map=" + map + + '}'; + } + } @Component @@ -74,7 +123,7 @@ class SampleRunner implements ApplicationRunner { * * user.name=Nacos user.age=25 * @param configInfo latest config data for specific dataId in Nacos - * server + * server */ @Override public void receiveConfigInfo(String configInfo) { @@ -101,19 +150,27 @@ class SampleRunner implements ApplicationRunner { @RefreshScope class SampleController { + @Autowired + UserConfig userConfig; + + @Autowired + private NacosConfigManager nacosConfigManager; + @Value("${user.name}") String userName; @Value("${user.age:25}") Integer age; - @Autowired - private NacosConfigManager nacosConfigManager; - @RequestMapping("/user") public String simple() { - return "Hello Nacos Config!" + "Hello " + userName + " " + age + "!" - + nacosConfigManager.getConfigService(); + return "Hello Nacos Config!" + "Hello " + userName + " " + age + " [UserConfig]: " + + userConfig + "!" + nacosConfigManager.getConfigService(); + } + + @RequestMapping("/bool") + public boolean bool() { + return (Boolean) (userConfig.getMap().get("2")); } } diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties index 2fc0eab44..71b87e610 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties @@ -13,6 +13,7 @@ spring.cloud.nacos.config.shared-configs[2]= common222.properties spring.cloud.nacos.config.extension-configs[0].data-id= extension1.properties spring.cloud.nacos.config.extension-configs[0].refresh= true spring.cloud.nacos.config.extension-configs[1]= extension2.properties +spring.cloud.nacos.config.extension-configs[2].data-id= extension3.json #spring.cloud.nacos.config.refresh-enabled=true