diff --git a/pom.xml b/pom.xml index 4c7dc45e..b1d6042c 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ spring-cloud-alibaba-dependencies spring-cloud-alibaba-sentinel spring-cloud-alibaba-sentinel-datasource - spring-cloud-alibaba-sentinel-zuul + spring-cloud-alibaba-sentinel-gateway spring-cloud-alibaba-nacos-config spring-cloud-alibaba-nacos-discovery spring-cloud-alibaba-seata diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index ccb740da..69b9e5ff 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -152,6 +152,11 @@ sentinel-zuul-adapter ${sentinel.version} + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + ${sentinel.version} + com.alibaba.csp sentinel-transport-simple-http @@ -192,6 +197,11 @@ sentinel-spring-webflux-adapter ${sentinel.version} + + com.alibaba.csp + sentinel-api-gateway-adapter-common + ${sentinel.version} + @@ -258,7 +268,7 @@ org.springframework.cloud - spring-cloud-alibaba-sentinel-zuul + spring-cloud-alibaba-sentinel-gateway ${project.version} diff --git a/spring-cloud-alibaba-examples/pom.xml b/spring-cloud-alibaba-examples/pom.xml index 7e810f19..addee644 100644 --- a/spring-cloud-alibaba-examples/pom.xml +++ b/spring-cloud-alibaba-examples/pom.xml @@ -22,6 +22,8 @@ sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api sentinel-example/sentinel-webflux-example + sentinel-example/sentinel-spring-cloud-gateway-example + sentinel-example/sentinel-zuul-example nacos-example/nacos-discovery-example nacos-example/nacos-config-example nacos-example/nacos-gateway-example diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/pom.xml new file mode 100644 index 00000000..e2979eb1 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/pom.xml @@ -0,0 +1,82 @@ + + + + + org.springframework.cloud + spring-cloud-alibaba-examples + 0.9.1.BUILD-SNAPSHOT + ../../pom.xml + + 4.0.0 + + + sentinel-spring-cloud-gateway-example + jar + Example demonstrating how to use sentinel with spring cloud gateway + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + org.springframework.cloud + spring-cloud-alibaba-sentinel-gateway + + + + + + + + + + + + + + + + + + + + + + + + + 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/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/MySCGConfiguration.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/MySCGConfiguration.java new file mode 100644 index 00000000..0c39e3f7 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/MySCGConfiguration.java @@ -0,0 +1,48 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; + +/** + * @author Jim + */ +@Configuration +public class MySCGConfiguration { + + @Bean + public BlockRequestHandler blockRequestHandler() { + return new BlockRequestHandler() { + @Override + public Mono handleRequest(ServerWebExchange exchange, Throwable t) { + return ServerResponse.status(444) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(fromObject("SCS Sentinel block")); + } + }; + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesWebFluxController.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesWebFluxController.java new file mode 100644 index 00000000..7767a871 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesWebFluxController.java @@ -0,0 +1,54 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import java.util.List; +import java.util.Set; + +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +/** + * @author Jim + */ +@RestController +public class RulesWebFluxController { + + @GetMapping("/api") + public Mono> apiRules() { + return Mono.just(GatewayApiDefinitionManager.getApiDefinitions()); + } + + @GetMapping("/gateway") + public Mono> apiGateway() { + return Mono.just(GatewayRuleManager.getRules()); + } + + @GetMapping("/flow") + public Mono> apiFlow() { + return Mono.just(FlowRuleManager.getRules()); + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelSpringCloudGatewayApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelSpringCloudGatewayApplication.java new file mode 100644 index 00000000..786d8dcd --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelSpringCloudGatewayApplication.java @@ -0,0 +1,33 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Jim + */ +@SpringBootApplication +public class SentinelSpringCloudGatewayApplication { + + public static void main(String[] args) { + //GatewayCallbackManager.setRequestOriginParser(s -> "123"); + SpringApplication.run(SentinelSpringCloudGatewayApplication.class, args); + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/api.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/api.json new file mode 100644 index 00000000..6de3c4fb --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/api.json @@ -0,0 +1,32 @@ +[ + { + "apiName": "some_customized_api", + "predicateItems": [ + { + "pattern": "/product/baz" + }, + { + "pattern": "/product/foo/**", + "matchStrategy": 1 + }, + { + "items": [ + { + "pattern": "/spring-cloud/**" + }, + { + "pattern": "/spring-cloud-alibaba/**" + } + ] + } + ] + }, + { + "apiName": "another_customized_api", + "predicateItems": [ + { + "pattern": "/ahas" + } + ] + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml new file mode 100644 index 00000000..a614f5b7 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml @@ -0,0 +1,37 @@ +server: + port: 18085 +spring: + application: + name: sentinel-spring-cloud-gateway + cloud: + gateway: + enabled: true + discovery: + locator: + lower-case-service-id: true + routes: + # Add your routes here. + - id: aliyun_route + uri: https://www.aliyun.com/ + predicates: + - Path=/product/** + - id: httpbin_route + uri: https://httpbin.org + predicates: + - Path=/httpbin/** + filters: + - RewritePath=/httpbin/(?.*), /$\{segment} + + sentinel: + datasource.ds2.file: + file: "classpath: gateway.json" + ruleType: gw-flow + datasource.ds1.file: + file: "classpath: api.json" + ruleType: gw-api-group + transport: + dashboard: localhost:8080 + filter: + enabled: true + +management.endpoints.web.exposure.include: "*" \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/gateway.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/gateway.json new file mode 100644 index 00000000..b08f71fc --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/gateway.json @@ -0,0 +1,22 @@ +[ + { + "resource": "some_customized_api", + "count": 1 + }, + { + "resource": "httpbin_route", + "count": 0, + "paramItem": { + "parseStrategy": 2, + "fieldName": "Spring-Cloud-Alibaba" + } + }, + { + "resource": "httpbin_route", + "count": 0, + "paramItem": { + "parseStrategy": 3, + "fieldName": "name" + } + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/pom.xml new file mode 100644 index 00000000..0f0b0c09 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/pom.xml @@ -0,0 +1,82 @@ + + + + + org.springframework.cloud + spring-cloud-alibaba-examples + 0.9.1.BUILD-SNAPSHOT + ../../pom.xml + + 4.0.0 + + + sentinel-zuul-example + jar + Example demonstrating how to use sentinel with zuul + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + + + + org.springframework.cloud + spring-cloud-alibaba-sentinel-gateway + + + + + + + + + + + + + + + + + + + + + + + + + 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/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesController.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesController.java new file mode 100644 index 00000000..01411ab7 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/RulesController.java @@ -0,0 +1,53 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import java.util.List; +import java.util.Set; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; + +/** + * @author Jim + */ +@RestController +public class RulesController { + + @GetMapping("/api") + public Set apiRules() { + return GatewayApiDefinitionManager.getApiDefinitions(); + } + + @GetMapping("/gateway") + public Set apiGateway() { + return GatewayRuleManager.getRules(); + } + + @GetMapping("/flow") + public List apiFlow() { + return FlowRuleManager.getRules(); + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelZuulApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelZuulApplication.java new file mode 100644 index 00000000..7e99e220 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/SentinelZuulApplication.java @@ -0,0 +1,34 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +/** + * @author Jim + */ +@SpringBootApplication +@EnableZuulProxy +public class SentinelZuulApplication { + + public static void main(String[] args) { + SpringApplication.run(SentinelZuulApplication.class, args); + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ZuulConfiguration.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ZuulConfiguration.java new file mode 100644 index 00000000..796241a2 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ZuulConfiguration.java @@ -0,0 +1,66 @@ +/* + * 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 org.springframework.cloud.alibaba.cloud.examples; + +import javax.servlet.http.HttpServletRequest; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.RequestOriginParser; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.BlockResponse; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Jim + */ +@Configuration +public class ZuulConfiguration { + + @Bean + public ZuulBlockFallbackProvider zuulBlockFallbackProvider1() { + return new ZuulBlockFallbackProvider() { + @Override + public String getRoute() { + return "*"; + } + + @Override + public BlockResponse fallbackResponse(String route, Throwable cause) { + if (route.equals("my-service3")) { + return new BlockResponse(433, "Sentinel Block3", route); + } else if (route.equals("my-service4")) { + return new BlockResponse(444, "my-service4", route); + } else { + return new BlockResponse(499, "Sentinel Block 499", route); + } + } + }; + } + + @Bean + public RequestOriginParser requestOriginParser() { + return new RequestOriginParser() { + + @Override + public String parseOrigin(HttpServletRequest request) { + return "123"; + } + }; + } + +} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/api.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/api.json new file mode 100644 index 00000000..6de3c4fb --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/api.json @@ -0,0 +1,32 @@ +[ + { + "apiName": "some_customized_api", + "predicateItems": [ + { + "pattern": "/product/baz" + }, + { + "pattern": "/product/foo/**", + "matchStrategy": 1 + }, + { + "items": [ + { + "pattern": "/spring-cloud/**" + }, + { + "pattern": "/spring-cloud-alibaba/**" + } + ] + } + ] + }, + { + "apiName": "another_customized_api", + "predicateItems": [ + { + "pattern": "/ahas" + } + ] + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/application.yaml new file mode 100644 index 00000000..0e9d9abf --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/application.yaml @@ -0,0 +1,40 @@ +server: + port: 18086 +spring: + application: + name: sentinel-zuul + cloud: + sentinel: + datasource.ds2.file: + file: "classpath: gateway.json" + ruleType: gw-flow + datasource.ds1.file: + file: "classpath: api.json" + ruleType: gw-api-group + transport: + dashboard: localhost:8080 + filter: + enabled: false + +management.endpoints.web.exposure.include: "*" + + +zuul.routes.my-service.path: "/product/foo/**" +zuul.routes.my-service.service-id: "my-service" + +zuul.routes.my-service2.path: "/my-service2/**" +zuul.routes.my-service2.service-id: "my-service2" + +zuul.routes.my-service3.path: "/my-service3/**" +zuul.routes.my-service3.service-id: "my-service3" + +zuul.routes.my-service4.path: "/my-service4/**" +zuul.routes.my-service4.service-id: "my-service4" + + +spring.cloud.sentinel.zuul.order.pre: 2000 +spring.cloud.sentinel.zuul.order.post: 500 +spring.cloud.sentinel.zuul.order.error: -100 + + +spring.cloud.sentinel.zuul.enabled: true \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/gateway.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/gateway.json new file mode 100644 index 00000000..b3effe88 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/resources/gateway.json @@ -0,0 +1,26 @@ +[ + { + "resource": "some_customized_api", + "count": 0 + }, + { + "resource": "my-service2", + "count": 0 + }, + { + "resource": "my-service3", + "count": 0, + "paramItem": { + "parseStrategy": 2, + "fieldName": "Spring-Cloud-Alibaba" + } + }, + { + "resource": "my-service4", + "count": 0, + "paramItem": { + "parseStrategy": 3, + "fieldName": "name" + } + } +] diff --git a/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-sentinel-datasource/pom.xml index 63203844..6dfee847 100644 --- a/spring-cloud-alibaba-sentinel-datasource/pom.xml +++ b/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -27,6 +27,12 @@ true + + com.alibaba.csp + sentinel-api-gateway-adapter-common + true + + com.alibaba.csp sentinel-datasource-nacos diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java index e59a5735..2318f321 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java @@ -6,6 +6,8 @@ import java.util.Optional; import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; import org.springframework.util.StringUtils; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.slots.block.AbstractRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; @@ -40,7 +42,15 @@ public enum RuleType { /** * authority */ - AUTHORITY("authority", AuthorityRule.class); + AUTHORITY("authority", AuthorityRule.class), + /** + * gateway flow + */ + GW_FLOW("gw-flow", GatewayFlowRule.class), + /** + * api + */ + GW_API_GROUP("gw-api-group", ApiDefinition.class); /** * alias for {@link AbstractRule} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java index 272252c2..0b830217 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java @@ -4,7 +4,10 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; +import org.springframework.core.env.Environment; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.datasource.AbstractDataSource; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; @@ -28,6 +31,8 @@ public class AbstractDataSourceProperties { private String converterClass; @JsonIgnore private final String factoryBeanName; + @JsonIgnore + private Environment env; public AbstractDataSourceProperties(String factoryBeanName) { this.factoryBeanName = factoryBeanName; @@ -61,6 +66,14 @@ public class AbstractDataSourceProperties { return factoryBeanName; } + protected Environment getEnv() { + return env; + } + + public void setEnv(Environment env) { + this.env = env; + } + public void preCheck(String dataSourceName) { } @@ -82,6 +95,12 @@ public class AbstractDataSourceProperties { case AUTHORITY: AuthorityRuleManager.register2Property(dataSource.getProperty()); break; + case GW_FLOW: + GatewayRuleManager.register2Property(dataSource.getProperty()); + break; + case GW_API_GROUP: + GatewayApiDefinitionManager.register2Property(dataSource.getProperty()); + break; default: break; } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java index 9df4d473..12c6e7f7 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java @@ -2,8 +2,6 @@ package org.springframework.cloud.alibaba.sentinel.datasource.config; import javax.validation.constraints.NotEmpty; -import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; -import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceFactoryBean; import org.springframework.util.StringUtils; @@ -34,9 +32,13 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { @Override public void preCheck(String dataSourceName) { - if (StringUtils.isEmpty(serverAddr) && acmPropertiesInvalid()) { - throw new IllegalArgumentException( - "NacosDataSource properties value not correct. serverAddr is empty but there is empty value in accessKey, secretKey, endpoint, namespace property"); + 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"); + } } } @@ -96,9 +98,4 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { this.secretKey = secretKey; } - public boolean acmPropertiesInvalid() { - return StringUtils.isEmpty(endpoint) || StringUtils.isEmpty(accessKey) - || StringUtils.isEmpty(secretKey) || StringUtils.isEmpty(namespace); - } - } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java index 0ebfee4d..7bbece26 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java @@ -1,8 +1,7 @@ package org.springframework.cloud.alibaba.sentinel.datasource.config; -import javax.validation.constraints.NotEmpty; - import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean; +import org.springframework.util.StringUtils; /** * Zookeeper Properties class Using by {@link DataSourcePropertiesConfiguration} and @@ -16,7 +15,6 @@ public class ZookeeperDataSourceProperties extends AbstractDataSourceProperties super(ZookeeperDataSourceFactoryBean.class.getName()); } - @NotEmpty private String serverAddr; private String path; @@ -25,6 +23,18 @@ public class ZookeeperDataSourceProperties extends AbstractDataSourceProperties private String dataId; + @Override + public void preCheck(String dataSourceName) { + if (StringUtils.isEmpty(serverAddr)) { + serverAddr = this.getEnv() + .getProperty("spring.cloud.sentinel.datasource.zk.server-addr", ""); + if (StringUtils.isEmpty(serverAddr)) { + throw new IllegalArgumentException( + "ZookeeperDataSource server-addr is empty"); + } + } + } + public String getServerAddr() { return serverAddr; } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java index 302bcd45..649f8f3b 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java @@ -1,7 +1,20 @@ package org.springframework.cloud.alibaba.sentinel.datasource.converter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; +import org.springframework.util.StringUtils; + +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; @@ -13,15 +26,6 @@ import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; -import org.springframework.util.StringUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; /** * Convert sentinel rules for json or xml array Using strict mode to parse json or xml @@ -34,8 +38,8 @@ import java.util.Optional; * @see ParamFlowRule * @see ObjectMapper */ -public abstract class SentinelConverter - implements Converter> { +public abstract class SentinelConverter + implements Converter> { private static final Logger log = LoggerFactory.getLogger(SentinelConverter.class); @@ -49,11 +53,20 @@ public abstract class SentinelConverter } @Override - public List convert(String source) { - List ruleList = new ArrayList<>(); + public Collection convert(String source) { + Collection ruleCollection; + + // hard code + if (ruleClass == GatewayFlowRule.class || ruleClass == ApiDefinition.class) { + ruleCollection = new HashSet<>(); + } + else { + ruleCollection = new ArrayList<>(); + } + if (StringUtils.isEmpty(source)) { log.warn("converter can not convert rules because source is empty"); - return ruleList; + return ruleCollection; } try { List sourceArray = objectMapper.readValue(source, @@ -70,11 +83,11 @@ public abstract class SentinelConverter } Optional.ofNullable(convertRule(item)) - .ifPresent(convertRule -> ruleList.add(convertRule)); + .ifPresent(convertRule -> ruleCollection.add(convertRule)); }); - if (ruleList.size() != sourceArray.size()) { - throw new IllegalArgumentException("convert " + ruleList.size() + if (ruleCollection.size() != sourceArray.size()) { + throw new IllegalArgumentException("convert " + ruleCollection.size() + " rules but there are " + sourceArray.size() + " rules from datasource. RuleClass: " + ruleClass.getSimpleName()); @@ -83,12 +96,12 @@ public abstract class SentinelConverter catch (Exception e) { throw new RuntimeException("convert error: " + e.getMessage(), e); } - return ruleList; + return ruleCollection; } - private AbstractRule convertRule(String ruleStr) { + private Object convertRule(String ruleStr) { try { - final AbstractRule rule = objectMapper.readValue(ruleStr, ruleClass); + final Object rule = objectMapper.readValue(ruleStr, ruleClass); RuleType ruleType = RuleType.getByClass(ruleClass).get(); switch (ruleType) { case FLOW: diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java index ddca34cb..ef616096 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java @@ -1,10 +1,10 @@ package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; +import org.springframework.beans.factory.FactoryBean; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource; -import org.springframework.beans.factory.FactoryBean; - /** * A {@link FactoryBean} for creating {@link ApolloDataSource} instance. * @@ -13,51 +13,51 @@ import org.springframework.beans.factory.FactoryBean; */ public class ApolloDataSourceFactoryBean implements FactoryBean { - private String namespaceName; - private String flowRulesKey; - private String defaultFlowRuleValue; - private Converter converter; + private String namespaceName; + private String flowRulesKey; + private String defaultFlowRuleValue; + private Converter converter; - @Override - public ApolloDataSource getObject() throws Exception { - return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, - converter); - } + @Override + public ApolloDataSource getObject() throws Exception { + return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, + converter); + } - @Override - public Class getObjectType() { - return ApolloDataSource.class; - } + @Override + public Class getObjectType() { + return ApolloDataSource.class; + } - public String getNamespaceName() { - return namespaceName; - } + public String getNamespaceName() { + return namespaceName; + } - public void setNamespaceName(String namespaceName) { - this.namespaceName = namespaceName; - } + public void setNamespaceName(String namespaceName) { + this.namespaceName = namespaceName; + } - public String getFlowRulesKey() { - return flowRulesKey; - } + public String getFlowRulesKey() { + return flowRulesKey; + } - public void setFlowRulesKey(String flowRulesKey) { - this.flowRulesKey = flowRulesKey; - } + public void setFlowRulesKey(String flowRulesKey) { + this.flowRulesKey = flowRulesKey; + } - public String getDefaultFlowRuleValue() { - return defaultFlowRuleValue; - } + public String getDefaultFlowRuleValue() { + return defaultFlowRuleValue; + } - public void setDefaultFlowRuleValue(String defaultFlowRuleValue) { - this.defaultFlowRuleValue = defaultFlowRuleValue; - } + public void setDefaultFlowRuleValue(String defaultFlowRuleValue) { + this.defaultFlowRuleValue = defaultFlowRuleValue; + } - public Converter getConverter() { - return converter; - } + public Converter getConverter() { + return converter; + } - public void setConverter(Converter converter) { - this.converter = converter; - } + public void setConverter(Converter converter) { + this.converter = converter; + } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java index 69ced480..13c3830b 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java @@ -3,11 +3,11 @@ package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; import java.io.File; import java.nio.charset.Charset; +import org.springframework.beans.factory.FactoryBean; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; -import org.springframework.beans.factory.FactoryBean; - /** * A {@link FactoryBean} for creating {@link FileRefreshableDataSource} instance. * @@ -23,7 +23,7 @@ public class FileRefreshableDataSourceFactoryBean private int bufSize; private Converter converter; - @Override + @Override public FileRefreshableDataSource getObject() throws Exception { return new FileRefreshableDataSource(new File(file), converter, recommendRefreshMs, bufSize, Charset.forName(charset)); diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java index d7894418..7d4e65b4 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -1,12 +1,13 @@ package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; +import java.util.Properties; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.util.StringUtils; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; import com.alibaba.nacos.api.PropertyKeyConst; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.util.StringUtils; - -import java.util.Properties; /** * A {@link FactoryBean} for creating {@link NacosDataSource} instance. diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java index b266f01f..ae7142c0 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java @@ -1,11 +1,11 @@ package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; - import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.FactoryBean; +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; + /** * A {@link FactoryBean} for creating {@link ZookeeperDataSource} instance. * @@ -14,68 +14,69 @@ import org.springframework.beans.factory.FactoryBean; */ public class ZookeeperDataSourceFactoryBean implements FactoryBean { - private String serverAddr; + private String serverAddr; - private String path; + private String path; - private String groupId; - private String dataId; + private String groupId; + private String dataId; - private Converter converter; + private Converter converter; - @Override - public ZookeeperDataSource getObject() throws Exception { - if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) { - // the path will be /{groupId}/{dataId} - return new ZookeeperDataSource(serverAddr, groupId, dataId, converter); - } else { - // using path directly - return new ZookeeperDataSource(serverAddr, path, converter); - } - } + @Override + public ZookeeperDataSource getObject() throws Exception { + if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) { + // the path will be /{groupId}/{dataId} + return new ZookeeperDataSource(serverAddr, groupId, dataId, converter); + } + else { + // using path directly + return new ZookeeperDataSource(serverAddr, path, converter); + } + } - @Override - public Class getObjectType() { - return ZookeeperDataSource.class; - } + @Override + public Class getObjectType() { + return ZookeeperDataSource.class; + } - public String getServerAddr() { - return serverAddr; - } + public String getServerAddr() { + return serverAddr; + } - public void setServerAddr(String serverAddr) { - this.serverAddr = serverAddr; - } + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } - public String getPath() { - return path; - } + public String getPath() { + return path; + } - public void setPath(String path) { - this.path = path; - } + public void setPath(String path) { + this.path = path; + } - public String getGroupId() { - return groupId; - } + public String getGroupId() { + return groupId; + } - public void setGroupId(String groupId) { - this.groupId = groupId; - } + public void setGroupId(String groupId) { + this.groupId = groupId; + } - public String getDataId() { - return dataId; - } + public String getDataId() { + return dataId; + } - public void setDataId(String dataId) { - this.dataId = dataId; - } + public void setDataId(String dataId) { + this.dataId = dataId; + } - public Converter getConverter() { - return converter; - } + public Converter getConverter() { + return converter; + } - public void setConverter(Converter converter) { - this.converter = converter; - } + public void setConverter(Converter converter) { + this.converter = converter; + } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/test/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelConverterTests.java b/spring-cloud-alibaba-sentinel-datasource/src/test/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelConverterTests.java index c6ae7a67..c4ffdc3b 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/test/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelConverterTests.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/test/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelConverterTests.java @@ -46,7 +46,7 @@ public class SentinelConverterTests { @Test public void testJsonConverter() { JsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class); - List flowRules = jsonConverter + List flowRules = (List) jsonConverter .convert(readFileContent("classpath: flowrule.json")); assertEquals("json converter flow rule size was wrong", 1, flowRules.size()); assertEquals("json converter flow rule resource name was wrong", "resource", @@ -67,7 +67,7 @@ public class SentinelConverterTests { @Test public void testConverterEmptyContent() { JsonConverter jsonConverter = new JsonConverter(objectMapper, FlowRule.class); - List flowRules = jsonConverter.convert(""); + List flowRules = (List) jsonConverter.convert(""); assertEquals("json converter flow rule size was not empty", 0, flowRules.size()); } @@ -86,7 +86,7 @@ public class SentinelConverterTests { @Test public void testXmlConverter() { XmlConverter jsonConverter = new XmlConverter(xmlMapper, FlowRule.class); - List flowRules = jsonConverter + List flowRules = (List) jsonConverter .convert(readFileContent("classpath: flowrule.xml")); assertEquals("xml converter flow rule size was wrong", 2, flowRules.size()); assertEquals("xml converter flow rule1 resource name was wrong", "resource", diff --git a/spring-cloud-alibaba-sentinel-zuul/README.md b/spring-cloud-alibaba-sentinel-gateway/README.md similarity index 98% rename from spring-cloud-alibaba-sentinel-zuul/README.md rename to spring-cloud-alibaba-sentinel-gateway/README.md index 2d0d2fd1..8c8c4a02 100755 --- a/spring-cloud-alibaba-sentinel-zuul/README.md +++ b/spring-cloud-alibaba-sentinel-gateway/README.md @@ -14,7 +14,7 @@ Sentinel can provide `ServiceId` level and `API Path` level flow control for spr ```xml org.springframework.cloud - spring-cloud-alibaba-sentinel-zuul + spring-cloud-alibaba-sentinel-gateway x.y.z diff --git a/spring-cloud-alibaba-sentinel-zuul/pom.xml b/spring-cloud-alibaba-sentinel-gateway/pom.xml similarity index 73% rename from spring-cloud-alibaba-sentinel-zuul/pom.xml rename to spring-cloud-alibaba-sentinel-gateway/pom.xml index 3f59bc1f..7675db8f 100644 --- a/spring-cloud-alibaba-sentinel-zuul/pom.xml +++ b/spring-cloud-alibaba-sentinel-gateway/pom.xml @@ -10,19 +10,28 @@ 4.0.0 org.springframework.cloud - spring-cloud-alibaba-sentinel-zuul - Spring Cloud Alibaba Sentinel Zuul + spring-cloud-alibaba-sentinel-gateway + Spring Cloud Alibaba Sentinel Gateway org.springframework.cloud spring-cloud-starter-netflix-zuul - provided + true com.alibaba.csp sentinel-zuul-adapter + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + + + org.springframework.cloud + spring-cloud-starter-gateway + true + org.springframework.boot spring-boot-configuration-processor diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelSpringCloudGatewayAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelSpringCloudGatewayAutoConfiguration.java new file mode 100644 index 00000000..2293d1f3 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelSpringCloudGatewayAutoConfiguration.java @@ -0,0 +1,91 @@ +/* + * 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 org.springframework.cloud.alibaba.sentinel.gateway; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import javax.annotation.PostConstruct; + +import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler; +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.web.reactive.result.view.ViewResolver; + +/** + * @author Jim + */ +@Configuration +@ConditionalOnClass(GlobalFilter.class) +@ConditionalOnProperty(prefix = "spring.cloud.sentinel.spring-cloud-gateway", name = "enabled", havingValue = "true", + matchIfMissing = true) +public class SentinelSpringCloudGatewayAutoConfiguration { + + private static final Logger logger = LoggerFactory + .getLogger(SentinelSpringCloudGatewayAutoConfiguration.class); + + private final List viewResolvers; + private final ServerCodecConfigurer serverCodecConfigurer; + + @Autowired + private Optional blockRequestHandlerOptional; + + @PostConstruct + private void init() { + blockRequestHandlerOptional + .ifPresent(GatewayCallbackManager::setBlockHandler); + } + + public SentinelSpringCloudGatewayAutoConfiguration( + ObjectProvider> viewResolversProvider, + ServerCodecConfigurer serverCodecConfigurer) { + this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); + this.serverCodecConfigurer = serverCodecConfigurer; + } + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { + // Register the block exception handler for Spring Cloud Gateway. + logger.info("[Sentinel SpringCloudGateway] register SentinelGatewayBlockExceptionHandler"); + return new SentinelGatewayBlockExceptionHandler(viewResolvers, + serverCodecConfigurer); + } + + @Bean + @Order(-1) + public GlobalFilter sentinelGatewayFilter() { + logger.info("[Sentinel SpringCloudGateway] register SentinelGatewayFilter"); + return new SentinelGatewayFilter(); + } + +} diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelZuulAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelZuulAutoConfiguration.java new file mode 100644 index 00000000..54ded615 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelZuulAutoConfiguration.java @@ -0,0 +1,115 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.gateway; + +import java.util.Optional; + +import javax.annotation.PostConstruct; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.RequestOriginParser; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.ZuulGatewayCallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.http.ZuulServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.alibaba.sentinel.gateway.handler.FallBackProviderHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +/** + * Sentinel Spring Cloud Zuul AutoConfiguration + * + * @author tiger + */ +@Configuration +@ConditionalOnClass(ZuulServlet.class) +@ConditionalOnProperty(prefix = SentinelZuulAutoConfiguration.PREFIX, name = "enabled", havingValue = "true", + matchIfMissing = true) +public class SentinelZuulAutoConfiguration { + + private static final Logger logger = LoggerFactory + .getLogger(SentinelZuulAutoConfiguration.class); + + public static final String PREFIX = "spring.cloud.sentinel.zuul"; + + @Autowired + private Environment environment; + + @Autowired + private Optional requestOriginParserOptional; + + @PostConstruct + private void init() { + requestOriginParserOptional + .ifPresent(ZuulGatewayCallbackManager::setOriginParser); + } + + @Bean + public ZuulFilter sentinelZuulPreFilter() { + String preOrderStr = environment.getProperty(PREFIX + "." + "order.pre"); + int order = 10000; + try { + order = Integer.parseInt(preOrderStr); + } catch (NumberFormatException e) { + // ignore + } + logger.info("[Sentinel Zuul] register SentinelZuulPreFilter {}", order); + return new SentinelZuulPreFilter(order); + } + + @Bean + public ZuulFilter sentinelZuulPostFilter() { + String postOrderStr = environment.getProperty(PREFIX + "." + "order.post"); + int order = 1000; + try { + order = Integer.parseInt(postOrderStr); + } catch (NumberFormatException e) { + // ignore + } + logger.info("[Sentinel Zuul] register SentinelZuulPostFilter {}", order); + return new SentinelZuulPostFilter(order); + } + + @Bean + public ZuulFilter sentinelZuulErrorFilter() { + String errorOrderStr = environment.getProperty(PREFIX + "." + "order.error"); + int order = -1; + try { + order = Integer.parseInt(errorOrderStr); + } catch (NumberFormatException e) { + // ignore + } + logger.info("[Sentinel Zuul] register SentinelZuulErrorFilter {}", order); + return new SentinelZuulErrorFilter(order); + } + + @Bean + public FallBackProviderHandler fallBackProviderHandler( + DefaultListableBeanFactory beanFactory) { + return new FallBackProviderHandler(beanFactory); + } + +} diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/handler/FallBackProviderHandler.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/handler/FallBackProviderHandler.java new file mode 100644 index 00000000..e046ad64 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/handler/FallBackProviderHandler.java @@ -0,0 +1,44 @@ +package org.springframework.cloud.alibaba.sentinel.gateway.handler; + +import java.util.Map; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.DefaultBlockFallbackProvider; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager; +import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.util.CollectionUtils; + +/** + * @author tiger + */ +public class FallBackProviderHandler implements SmartInitializingSingleton { + + private static final Logger logger = LoggerFactory + .getLogger(FallBackProviderHandler.class); + + private final DefaultListableBeanFactory beanFactory; + + public FallBackProviderHandler(DefaultListableBeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + @Override + public void afterSingletonsInstantiated() { + Map providerMap = beanFactory + .getBeansOfType(ZuulBlockFallbackProvider.class); + if (!CollectionUtils.isEmpty(providerMap)) { + providerMap.forEach((k, v) -> { + logger.info("[Sentinel Zuul] Register provider name:{}, instance: {}", k, + v); + ZuulBlockFallbackManager.registerProvider(v); + }); + } else { + logger.info("[Sentinel Zuul] Register default fallback provider. "); + ZuulBlockFallbackManager.registerProvider(new DefaultBlockFallbackProvider()); + } + } +} diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..49a280be --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.cloud.alibaba.sentinel.gateway.SentinelZuulAutoConfiguration,\ +org.springframework.cloud.alibaba.sentinel.gateway.SentinelSpringCloudGatewayAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java b/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java deleted file mode 100644 index 311b4609..00000000 --- a/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * 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 - * - * http://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 org.springframework.cloud.alibaba.sentinel.zuul; - -import static org.springframework.cloud.commons.util.InetUtilsProperties.PREFIX; - -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.alibaba.sentinel.zuul.handler.FallBackProviderHandler; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.DefaultRequestOriginParser; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.RequestOriginParser; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter; - -import com.netflix.zuul.ZuulFilter; - -/** - * Sentinel Spring Cloud Zuul AutoConfiguration - * - * @author tiger - */ -@Configuration -@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) -public class SentinelZuulAutoConfiguration { - - @Bean - @ConditionalOnMissingBean(RequestOriginParser.class) - public RequestOriginParser requestOriginParser() { - return new DefaultRequestOriginParser(); - } - - @Bean - public ZuulFilter sentinelZuulPreFilter() { - // We can also provider the filter order in the constructor. - return new SentinelZuulPreFilter(); - } - - @Bean - public ZuulFilter sentinelZuulPostFilter() { - return new SentinelZuulPostFilter(); - } - - @Bean - public ZuulFilter sentinelZuulErrorFilter() { - return new SentinelZuulErrorFilter(); - } - - @Bean - public FallBackProviderHandler fallBackProviderListener( - DefaultListableBeanFactory beanFactory) { - return new FallBackProviderHandler(beanFactory); - } - -} diff --git a/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java b/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java deleted file mode 100644 index 0628d5d5..00000000 --- a/spring-cloud-alibaba-sentinel-zuul/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.zuul.handler; - -import java.util.Map; - -import org.apache.commons.collections.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; - -import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.DefaultBlockFallbackProvider; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager; -import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider; - -/** - * @author tiger - */ -public class FallBackProviderHandler implements SmartInitializingSingleton { - - private static final Logger logger = LoggerFactory - .getLogger(FallBackProviderHandler.class); - - private final DefaultListableBeanFactory beanFactory; - - public FallBackProviderHandler(DefaultListableBeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - @Override - public void afterSingletonsInstantiated() { - Map providerMap = beanFactory - .getBeansOfType(ZuulBlockFallbackProvider.class); - if (MapUtils.isNotEmpty(providerMap)) { - providerMap.forEach((k, v) -> { - logger.info("[Sentinel Zuul] Register provider name:{}, instance: {}", k, - v); - ZuulBlockFallbackManager.registerProvider(v); - }); - } - else { - logger.info("[Sentinel Zuul] Register default fallback provider. "); - ZuulBlockFallbackManager.registerProvider(new DefaultBlockFallbackProvider()); - } - } -} diff --git a/spring-cloud-alibaba-sentinel-zuul/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel-zuul/src/main/resources/META-INF/spring.factories deleted file mode 100644 index b4ced151..00000000 --- a/spring-cloud-alibaba-sentinel-zuul/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.alibaba.sentinel.zuul.SentinelZuulAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index a88c7f05..a832136b 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -105,6 +105,11 @@ provided + + com.alibaba.csp + sentinel-api-gateway-adapter-common + + diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java index 05984c24..00f7576e 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java @@ -16,6 +16,12 @@ package org.springframework.cloud.alibaba.sentinel.custom; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; @@ -31,8 +37,14 @@ import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConver import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.util.StringUtils; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateGroupItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; import com.alibaba.csp.sentinel.config.SentinelConfig; @@ -46,8 +58,15 @@ import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.alibaba.csp.sentinel.transport.config.TransportConfig; import com.alibaba.csp.sentinel.util.AppNameUtil; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** @@ -152,81 +171,164 @@ public class SentinelAutoConfiguration { @Bean public SentinelDataSourceHandler sentinelDataSourceHandler( - DefaultListableBeanFactory beanFactory) { - return new SentinelDataSourceHandler(beanFactory); + DefaultListableBeanFactory beanFactory, SentinelProperties sentinelProperties, + Environment env) { + return new SentinelDataSourceHandler(beanFactory, sentinelProperties, env); } @ConditionalOnClass(ObjectMapper.class) + @Configuration protected static class SentinelConverterConfiguration { - private ObjectMapper objectMapper = new ObjectMapper(); + static class ApiPredicateItemDeserializer + extends StdDeserializer { + private Map> registry = new HashMap>(); - public SentinelConverterConfiguration() { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, - false); + ApiPredicateItemDeserializer() { + super(ApiPredicateItem.class); + } + + void registerApiPredicateItem(String uniqueAttribute, + Class apiPredicateItemClass) { + registry.put(uniqueAttribute, apiPredicateItemClass); + } + + @Override + public ApiPredicateItem deserialize(JsonParser jp, + DeserializationContext ctxt) throws IOException { + ObjectMapper mapper = (ObjectMapper) jp.getCodec(); + ObjectNode root = mapper.readTree(jp); + Class apiPredicateItemClass = null; + Iterator> elementsIterator = root.fields(); + while (elementsIterator.hasNext()) { + Entry element = elementsIterator.next(); + String name = element.getKey(); + if (registry.containsKey(name)) { + apiPredicateItemClass = registry.get(name); + break; + } + } + if (apiPredicateItemClass == null) { + return null; + } + return mapper.readValue(root.toString(), apiPredicateItemClass); + } } - @Bean("sentinel-json-flow-converter") - public JsonConverter jsonFlowConverter() { - return new JsonConverter(objectMapper, FlowRule.class); + @Configuration + protected static class SentinelJsonConfiguration { + + private ObjectMapper objectMapper = new ObjectMapper(); + + public SentinelJsonConfiguration() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + + ApiPredicateItemDeserializer deserializer = new ApiPredicateItemDeserializer(); + deserializer.registerApiPredicateItem("pattern", + ApiPathPredicateItem.class); + deserializer.registerApiPredicateItem("items", + ApiPredicateGroupItem.class); + SimpleModule module = new SimpleModule( + "PolymorphicApiPredicateItemDeserializerModule", + new Version(1, 0, 0, null)); + module.addDeserializer(ApiPredicateItem.class, deserializer); + objectMapper.registerModule(module); + } + + @Bean("sentinel-json-flow-converter") + public JsonConverter jsonFlowConverter() { + return new JsonConverter(objectMapper, FlowRule.class); + } + + @Bean("sentinel-json-degrade-converter") + public JsonConverter jsonDegradeConverter() { + return new JsonConverter(objectMapper, DegradeRule.class); + } + + @Bean("sentinel-json-system-converter") + public JsonConverter jsonSystemConverter() { + return new JsonConverter(objectMapper, SystemRule.class); + } + + @Bean("sentinel-json-authority-converter") + public JsonConverter jsonAuthorityConverter() { + return new JsonConverter(objectMapper, AuthorityRule.class); + } + + @Bean("sentinel-json-param-flow-converter") + public JsonConverter jsonParamFlowConverter() { + return new JsonConverter(objectMapper, ParamFlowRule.class); + } + + @Bean("sentinel-json-gw-flow-converter") + public JsonConverter jsonGatewayFlowConverter() { + return new JsonConverter(objectMapper, GatewayFlowRule.class); + } + + @Bean("sentinel-json-gw-api-group-converter") + public JsonConverter jsonApiConverter() { + return new JsonConverter(objectMapper, ApiDefinition.class); + } } - @Bean("sentinel-json-degrade-converter") - public JsonConverter jsonDegradeConverter() { - return new JsonConverter(objectMapper, DegradeRule.class); + @ConditionalOnClass(XmlMapper.class) + @Configuration + protected static class SentinelXmlConfiguration { + + private XmlMapper xmlMapper = new XmlMapper(); + + public SentinelXmlConfiguration() { + xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + ApiPredicateItemDeserializer deserializer = new ApiPredicateItemDeserializer(); + deserializer.registerApiPredicateItem("pattern", + ApiPathPredicateItem.class); + deserializer.registerApiPredicateItem("items", + ApiPredicateGroupItem.class); + SimpleModule module = new SimpleModule( + "PolymorphicGatewayDeserializerModule", + new Version(1, 0, 0, null)); + module.addDeserializer(ApiPredicateItem.class, deserializer); + xmlMapper.registerModule(module); + } + + @Bean("sentinel-xml-flow-converter") + public XmlConverter xmlFlowConverter() { + return new XmlConverter(xmlMapper, FlowRule.class); + } + + @Bean("sentinel-xml-degrade-converter") + public XmlConverter xmlDegradeConverter() { + return new XmlConverter(xmlMapper, DegradeRule.class); + } + + @Bean("sentinel-xml-system-converter") + public XmlConverter xmlSystemConverter() { + return new XmlConverter(xmlMapper, SystemRule.class); + } + + @Bean("sentinel-xml-authority-converter") + public XmlConverter xmlAuthorityConverter() { + return new XmlConverter(xmlMapper, AuthorityRule.class); + } + + @Bean("sentinel-xml-param-flow-converter") + public XmlConverter xmlParamFlowConverter() { + return new XmlConverter(xmlMapper, ParamFlowRule.class); + } + + @Bean("sentinel-xml-gw-flow-converter") + public XmlConverter xmlGatewayFlowConverter() { + return new XmlConverter(xmlMapper, GatewayFlowRule.class); + } + + @Bean("sentinel-xml-gw-api-group-converter") + public XmlConverter xmlApiConverter() { + return new XmlConverter(xmlMapper, ApiDefinition.class); + } + } - - @Bean("sentinel-json-system-converter") - public JsonConverter jsonSystemConverter() { - return new JsonConverter(objectMapper, SystemRule.class); - } - - @Bean("sentinel-json-authority-converter") - public JsonConverter jsonAuthorityConverter() { - return new JsonConverter(objectMapper, AuthorityRule.class); - } - - @Bean("sentinel-json-param-flow-converter") - public JsonConverter jsonParamFlowConverter() { - return new JsonConverter(objectMapper, ParamFlowRule.class); - } - - } - - @ConditionalOnClass(XmlMapper.class) - protected static class SentinelXmlConfiguration { - - private XmlMapper xmlMapper = new XmlMapper(); - - public SentinelXmlConfiguration() { - xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - - @Bean("sentinel-xml-flow-converter") - public XmlConverter xmlFlowConverter() { - return new XmlConverter(xmlMapper, FlowRule.class); - } - - @Bean("sentinel-xml-degrade-converter") - public XmlConverter xmlDegradeConverter() { - return new XmlConverter(xmlMapper, DegradeRule.class); - } - - @Bean("sentinel-xml-system-converter") - public XmlConverter xmlSystemConverter() { - return new XmlConverter(xmlMapper, SystemRule.class); - } - - @Bean("sentinel-xml-authority-converter") - public XmlConverter xmlAuthorityConverter() { - return new XmlConverter(xmlMapper, AuthorityRule.class); - } - - @Bean("sentinel-xml-param-flow-converter") - public XmlConverter xmlParamFlowConverter() { - return new XmlConverter(xmlMapper, ParamFlowRule.class); - } - } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java index df57f919..6b5fce5f 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java @@ -1,29 +1,30 @@ package org.springframework.cloud.alibaba.sentinel.custom; -import com.alibaba.csp.sentinel.datasource.AbstractDataSource; -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.cloud.alibaba.sentinel.SentinelProperties; import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter; import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter; +import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import com.alibaba.csp.sentinel.datasource.AbstractDataSource; +import com.alibaba.csp.sentinel.datasource.ReadableDataSource; /** * Sentinel {@link ReadableDataSource} Handler Handle the configurations of @@ -47,12 +48,16 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton { private final DefaultListableBeanFactory beanFactory; - public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory) { - this.beanFactory = beanFactory; - } + private final SentinelProperties sentinelProperties; - @Autowired - private SentinelProperties sentinelProperties; + private final Environment env; + + public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory, + SentinelProperties sentinelProperties, Environment env) { + this.beanFactory = beanFactory; + this.sentinelProperties = sentinelProperties; + this.env = env; + } @Override public void afterSingletonsInstantiated() { @@ -68,6 +73,7 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton { } AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties .getValidDataSourceProperties(); + abstractDataSourceProperties.setEnv(env); abstractDataSourceProperties.preCheck(dataSourceName); registerBean(abstractDataSourceProperties, dataSourceName + "-sentinel-" + validFields.get(0) + "-datasource"); @@ -189,7 +195,7 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton { } private void logAndCheckRuleType(AbstractDataSource dataSource, String dataSourceName, - Class ruleClass) { + Class ruleClass) { Object ruleConfig; try { ruleConfig = dataSource.loadConfig(); @@ -199,8 +205,8 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton { + " loadConfig error: " + e.getMessage(), e); return; } - if (ruleConfig instanceof List) { - List convertedRuleList = (List) ruleConfig; + if (ruleConfig instanceof List || ruleConfig instanceof Set) { + Collection convertedRuleList = (Collection) ruleConfig; if (CollectionUtils.isEmpty(convertedRuleList)) { log.warn("[Sentinel Starter] DataSource {} rule list is empty.", dataSourceName);