From e840fd0b592257908f433ddd559488d3829614f0 Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Tue, 21 May 2019 16:34:08 +0800 Subject: [PATCH] refactor sentinel gateway module --- .../src/main/resources/application.yaml | 5 + .../sentinel/gateway/ConfigConstants.java | 33 ++++ .../sentinel/gateway/FallbackProperties.java | 80 +++++++++ ...elSpringCloudGatewayAutoConfiguration.java | 91 ----------- .../SentinelZuulAutoConfiguration.java | 115 ------------- .../handler/FallBackProviderHandler.java | 44 ----- .../scg/SentinelGatewayProperties.java | 42 +++++ .../scg/SentinelSCGAutoConfiguration.java | 152 ++++++++++++++++++ .../gateway/zuul/FallBackProviderHandler.java | 45 ++++++ .../zuul/SentinelZuulAutoConfiguration.java | 99 ++++++++++++ .../gateway/zuul/SentinelZuulProperties.java | 88 ++++++++++ .../main/resources/META-INF/spring.factories | 4 +- 12 files changed, 546 insertions(+), 252 deletions(-) create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java delete mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelSpringCloudGatewayAutoConfiguration.java delete mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelZuulAutoConfiguration.java delete mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/handler/FallBackProviderHandler.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java create mode 100644 spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java 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 index a614f5b7..b8fc8b38 100644 --- 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 @@ -33,5 +33,10 @@ spring: dashboard: localhost:8080 filter: enabled: true +# scg: +# fallback: +# mode: response +# response-status: 444 +# response-body: 1234 management.endpoints.web.exposure.include: "*" \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java new file mode 100644 index 00000000..e3766d88 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.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.sentinel.gateway; + +/** + * @author Jim + */ +public interface ConfigConstants { + + String APP_TYPE_ZUUL_GATEWAY = "12"; + + String ZUUl_PREFIX = "spring.cloud.sentinel.zuul"; + + String GATEWAY_PREFIX = "spring.cloud.sentinel.scg"; + + String FALLBACK_MSG_RESPONSE = "response"; + String FALLBACK_REDIRECT = "redirect"; + +} diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java new file mode 100644 index 00000000..d3de67cd --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java @@ -0,0 +1,80 @@ +/* + * 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 org.springframework.http.HttpStatus; + +/** + * @author Jim + */ +public class FallbackProperties { + + /** + * The fallback mode for sentinel spring-cloud-gateway. choose `redirect` or + * `response`. + */ + private String mode; + /** + * Redirect Url for `redirect` mode. + */ + private String redirect; + /** + * Response Body for `response` mode. + */ + private String responseBody; + /** + * Response Status for `response` mode. + */ + private Integer responseStatus = HttpStatus.TOO_MANY_REQUESTS.value(); + + public String getMode() { + return mode; + } + + public FallbackProperties setMode(String mode) { + this.mode = mode; + return this; + } + + public String getRedirect() { + return redirect; + } + + public FallbackProperties setRedirect(String redirect) { + this.redirect = redirect; + return this; + } + + public String getResponseBody() { + return responseBody; + } + + public FallbackProperties setResponseBody(String responseBody) { + this.responseBody = responseBody; + return this; + } + + public Integer getResponseStatus() { + return responseStatus; + } + + public FallbackProperties setResponseStatus(Integer responseStatus) { + this.responseStatus = responseStatus; + return this; + } + +} 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 deleted file mode 100644 index 2293d1f3..00000000 --- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelSpringCloudGatewayAutoConfiguration.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 deleted file mode 100644 index 54ded615..00000000 --- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/SentinelZuulAutoConfiguration.java +++ /dev/null @@ -1,115 +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.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 deleted file mode 100644 index e046ad64..00000000 --- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/handler/FallBackProviderHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -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/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java new file mode 100644 index 00000000..cfbdf9ab --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java @@ -0,0 +1,42 @@ +/* + * 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.scg; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants; +import org.springframework.cloud.alibaba.sentinel.gateway.FallbackProperties; + +/** + * @author Jim + */ +@ConfigurationProperties(prefix = ConfigConstants.GATEWAY_PREFIX) +public class SentinelGatewayProperties { + + @NestedConfigurationProperty + private FallbackProperties fallback; + + public FallbackProperties getFallback() { + return fallback; + } + + public SentinelGatewayProperties setFallback(FallbackProperties fallback) { + this.fallback = fallback; + return this; + } + +} diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java new file mode 100644 index 00000000..076b0b18 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.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 org.springframework.cloud.alibaba.sentinel.gateway.scg; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import javax.annotation.PostConstruct; + +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.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants; +import org.springframework.cloud.alibaba.sentinel.gateway.FallbackProperties; +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.MediaType; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.server.ServerWebExchange; + +import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; +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.callback.RedirectBlockRequestHandler; +import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; +import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.util.StringUtil; + +import reactor.core.publisher.Mono; + +/** + * @author Jim + */ +@Configuration +@ConditionalOnClass(GlobalFilter.class) +@ConditionalOnProperty(prefix = ConfigConstants.GATEWAY_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) +@EnableConfigurationProperties(SentinelGatewayProperties.class) +public class SentinelSCGAutoConfiguration { + + private static final Logger logger = LoggerFactory + .getLogger(SentinelSCGAutoConfiguration.class); + + private final List viewResolvers; + private final ServerCodecConfigurer serverCodecConfigurer; + + @Autowired + private Optional blockRequestHandlerOptional; + + @Autowired + private SentinelGatewayProperties gatewayProperties; + + @PostConstruct + private void init() { + // blockRequestHandlerOptional has low priority + blockRequestHandlerOptional.ifPresent(GatewayCallbackManager::setBlockHandler); + initAppType(); + initFallback(); + } + + public SentinelSCGAutoConfiguration( + ObjectProvider> viewResolversProvider, + ServerCodecConfigurer serverCodecConfigurer) { + this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); + this.serverCodecConfigurer = serverCodecConfigurer; + } + + private void initAppType() { + System.setProperty(SentinelConfig.APP_TYPE, + String.valueOf(SentinelGatewayConstants.APP_TYPE_GATEWAY)); + } + + private void initFallback() { + FallbackProperties fallbackProperties = gatewayProperties.getFallback(); + if (fallbackProperties == null + || StringUtil.isBlank(fallbackProperties.getMode())) { + return; + } + if (ConfigConstants.FALLBACK_MSG_RESPONSE.equals(fallbackProperties.getMode())) { + if (StringUtil.isNotBlank(fallbackProperties.getResponseBody())) { + GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() { + @Override + public Mono handleRequest(ServerWebExchange exchange, + Throwable t) { + return ServerResponse + .status(fallbackProperties.getResponseStatus()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(fromObject(fallbackProperties.getResponseBody())); + } + }); + logger.info( + "[Sentinel SpringCloudGateway] using AnonymousBlockRequestHandler, responseStatus: " + + fallbackProperties.getResponseStatus() + + ", responseBody: " + + fallbackProperties.getResponseStatus()); + } + } + String redirectUrl = fallbackProperties.getRedirect(); + if (ConfigConstants.FALLBACK_REDIRECT.equals(fallbackProperties.getMode()) + && StringUtil.isNotBlank(redirectUrl)) { + GatewayCallbackManager + .setBlockHandler(new RedirectBlockRequestHandler(redirectUrl)); + logger.info( + "[Sentinel SpringCloudGateway] using RedirectBlockRequestHandler, redirectUrl: " + + redirectUrl); + } + } + + @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/zuul/FallBackProviderHandler.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java new file mode 100644 index 00000000..be27b988 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java @@ -0,0 +1,45 @@ +package org.springframework.cloud.alibaba.sentinel.gateway.zuul; + +import java.util.Map; + +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; + +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 (!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/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java new file mode 100644 index 00000000..7ed86588 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java @@ -0,0 +1,99 @@ +/* + * 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.zuul; + +import java.util.Optional; + +import javax.annotation.PostConstruct; + +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.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +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.alibaba.csp.sentinel.config.SentinelConfig; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.http.ZuulServlet; + +/** + * Sentinel Spring Cloud Zuul AutoConfiguration + * + * @author tiger + */ +@Configuration +@ConditionalOnClass(ZuulServlet.class) +@ConditionalOnProperty(prefix = ConfigConstants.ZUUl_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) +@EnableConfigurationProperties(SentinelZuulProperties.class) +public class SentinelZuulAutoConfiguration { + + private static final Logger logger = LoggerFactory + .getLogger(SentinelZuulAutoConfiguration.class); + + @Autowired + private Optional requestOriginParserOptional; + + @Autowired + private SentinelZuulProperties zuulProperties; + + @PostConstruct + private void init() { + requestOriginParserOptional + .ifPresent(ZuulGatewayCallbackManager::setOriginParser); + System.setProperty(SentinelConfig.APP_TYPE, + String.valueOf(ConfigConstants.APP_TYPE_ZUUL_GATEWAY)); + } + + @Bean + public ZuulFilter sentinelZuulPreFilter() { + logger.info("[Sentinel Zuul] register SentinelZuulPreFilter {}", + zuulProperties.getOrder().getPre()); + return new SentinelZuulPreFilter(zuulProperties.getOrder().getPre()); + } + + @Bean + public ZuulFilter sentinelZuulPostFilter() { + logger.info("[Sentinel Zuul] register SentinelZuulPostFilter {}", + zuulProperties.getOrder().getPost()); + return new SentinelZuulPostFilter(zuulProperties.getOrder().getPost()); + } + + @Bean + public ZuulFilter sentinelZuulErrorFilter() { + logger.info("[Sentinel Zuul] register SentinelZuulErrorFilter {}", + zuulProperties.getOrder().getError()); + return new SentinelZuulErrorFilter(zuulProperties.getOrder().getError()); + } + + @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/zuul/SentinelZuulProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java new file mode 100644 index 00000000..102baae8 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java @@ -0,0 +1,88 @@ +/* + * 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.zuul; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants; + +import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; +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; + +/** + * @author Jim + */ +@ConfigurationProperties(prefix = ConfigConstants.ZUUl_PREFIX) +public class SentinelZuulProperties { + + @NestedConfigurationProperty + private SentinelZuulProperties.Order order; + + public Order getOrder() { + return order; + } + + public SentinelZuulProperties setOrder(Order order) { + this.order = order; + return this; + } + + public static class Order { + + /** + * The order of {@link SentinelZuulPreFilter}. + */ + private int pre = 10000; + + /** + * The order of {@link SentinelZuulPostFilter}. + */ + private int post = ZuulConstant.SEND_RESPONSE_FILTER_ORDER; + + /** + * The order of {@link SentinelZuulErrorFilter}. + */ + private int error = -1; + + public int getPre() { + return pre; + } + + public void setPre(int pre) { + this.pre = pre; + } + + public int getPost() { + return post; + } + + public void setPost(int post) { + this.post = post; + } + + public int getError() { + return error; + } + + public void setError(int error) { + this.error = error; + } + } + +} 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 index 49a280be..15297fce 100644 --- 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 @@ -1,3 +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 +org.springframework.cloud.alibaba.sentinel.gateway.zuul.SentinelZuulAutoConfiguration,\ +org.springframework.cloud.alibaba.sentinel.gateway.scg.SentinelSCGAutoConfiguration \ No newline at end of file