diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml index c61c0009..5f5ccda7 100755 --- a/sentinel-demo/pom.xml +++ b/sentinel-demo/pom.xml @@ -32,6 +32,7 @@ sentinel-demo-command-handler sentinel-demo-spring-webflux sentinel-demo-apache-dubbo + sentinel-demo-spring-cloud-gateway diff --git a/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml b/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml new file mode 100644 index 00000000..bbdf5c79 --- /dev/null +++ b/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml @@ -0,0 +1,41 @@ + + + + sentinel-demo + com.alibaba.csp + 1.6.0-SNAPSHOT + + 4.0.0 + + sentinel-demo-spring-cloud-gateway + + + 1.8 + 1.8 + + + + + org.springframework.cloud + spring-cloud-starter-gateway + 2.1.1.RELEASE + + + org.springframework.boot + spring-boot-starter-webflux + 2.1.4.RELEASE + + + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + ${project.version} + + + com.alibaba.csp + sentinel-transport-simple-http + + + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayConfiguration.java b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayConfiguration.java new file mode 100644 index 00000000..5f1cc56a --- /dev/null +++ b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayConfiguration.java @@ -0,0 +1,142 @@ +/* + * Copyright 1999-2019 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 + * + * 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.csp.sentinel.demo.spring.sc.gateway; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; +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.ApiPredicateItem; +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.GatewayParamFlowItem; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; +import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; +import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; + +import org.springframework.beans.factory.ObjectProvider; +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 Eric Zhao + */ +@Configuration +public class GatewayConfiguration { + + private final List viewResolvers; + private final ServerCodecConfigurer serverCodecConfigurer; + + public GatewayConfiguration(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. + return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); + } + + @Bean + @Order(-1) + public GlobalFilter sentinelGatewayFilter() { + return new SentinelGatewayFilter(); + } + + @PostConstruct + public void doInit() { + initCustomizedApis(); + initGatewayRules(); + } + + private void initCustomizedApis() { + Set definitions = new HashSet<>(); + ApiDefinition api1 = new ApiDefinition("some_customized_api") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/ahas")); + add(new ApiPathPredicateItem().setPattern("/product/**") + .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_PREFIX)); + }}); + ApiDefinition api2 = new ApiDefinition("another_customized_api") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/**") + .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_PREFIX)); + }}); + definitions.add(api1); + definitions.add(api2); + GatewayApiDefinitionManager.loadApiDefinitions(definitions); + } + + private void initGatewayRules() { + Set rules = new HashSet<>(); + rules.add(new GatewayFlowRule("aliyun_route") + .setCount(10) + .setIntervalSec(1) + ); + rules.add(new GatewayFlowRule("aliyun_route") + .setCount(2) + .setIntervalSec(2) + .setBurst(2) + .setParamItem(new GatewayParamFlowItem() + .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP) + ) + ); + rules.add(new GatewayFlowRule("httpbin_route") + .setCount(10) + .setIntervalSec(1) + .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER) + .setMaxQueueingTimeoutMs(600) + .setParamItem(new GatewayParamFlowItem() + .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER) + .setFieldName("X-Sentinel-Flag") + ) + ); + rules.add(new GatewayFlowRule("httpbin_route") + .setCount(1) + .setIntervalSec(1) + .setParamItem(new GatewayParamFlowItem() + .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM) + .setFieldName("pa") + ) + ); + + rules.add(new GatewayFlowRule("some_customized_api") + .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME) + .setCount(5) + .setIntervalSec(1) + .setParamItem(new GatewayParamFlowItem() + .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM) + .setFieldName("pn") + ) + ); + GatewayRuleManager.loadRules(rules); + } +} diff --git a/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayDemoApplication.java b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayDemoApplication.java new file mode 100644 index 00000000..2a9ccecd --- /dev/null +++ b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayDemoApplication.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 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 + * + * 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.csp.sentinel.demo.spring.sc.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + *

A demo for Spring Cloud Gateway.

+ * + *

To integrate with Sentinel dashboard, you can run the demo with the parameters (an example): + * -Dproject.name=spring-cloud-gateway -Dcsp.sentinel.dashboard.server=localhost:8080 + * -Dcsp.sentinel.api.port=8720 -Dcsp.sentinel.app.type=1 + * + *

+ * + * @author Eric Zhao + */ +@SpringBootApplication +public class GatewayDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(GatewayDemoApplication.class, args); + } +} diff --git a/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/resources/application.yml b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/resources/application.yml new file mode 100644 index 00000000..9acdfe7a --- /dev/null +++ b/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/resources/application.yml @@ -0,0 +1,23 @@ +server: + port: 8090 +spring: + application: + name: 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} \ No newline at end of file