From 0427dcfa3d6cb106475b6160d5d22b8eb3f0b11b Mon Sep 17 00:00:00 2001 From: barney <15270405776@163.com> Date: Mon, 8 May 2023 17:17:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Egateway=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=92=8C=E5=88=86=E7=BB=84=E9=99=90=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 19 +++ gateway/pom.xml | 26 +++++ .../bnblogs/gateway/GatewayApplication.java | 3 +- .../config/SentinelRouteConfiguration.java | 108 ++++++++++++++++++ gateway/src/main/resources/application.yml | 18 +-- provider/pom.xml | 6 + .../provider/controller/IndexController.java | 20 ++++ 7 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 gateway/src/main/java/cc/bnblogs/gateway/config/SentinelRouteConfiguration.java diff --git a/README.md b/README.md index 0103ff3..9ee9396 100644 --- a/README.md +++ b/README.md @@ -1 +1,20 @@ ### 基于SpringCloudAlibaba + +#### 版本关系 + +| 依赖 | 版本号 | +| :-------------------------------------: | :----------: | +| `SpringBoot` | `2.6.11` | +| `Spring Cloud` | ` 2021.0.4` | +| `Spring Cloud Alibaba` | `2021.0.4.0` | +| `Sentinel jar ` | `1.8.5` | +| `Nacos jar ` | `2.0.4` | +| `RocketMQ` | `4.9.4` | +| `Seata` | `1.5.2` | +| `spring-cloud-starter-loadbalancer` | `3.1.4` | +| `spring-cloud-starter-gateway` | `3.1.4` | +| `spring-cloud-starter-alibaba-sentinel` | `2021.0.4.0` | + +#### 详细文档 + +地址:[https://hugo.bnblogs.cc/springcloud%E7%AC%94%E8%AE%B0/#%E5%9F%BA%E4%BA%8Enacos%E8%8E%B7%E5%8F%96%E5%85%B6%E4%BB%96%E6%9C%8D%E5%8A%A1](https://hugo.bnblogs.cc/springcloud%E7%AC%94%E8%AE%B0/#%E5%9F%BA%E4%BA%8Enacos%E8%8E%B7%E5%8F%96%E5%85%B6%E4%BB%96%E6%9C%8D%E5%8A%A1) diff --git a/gateway/pom.xml b/gateway/pom.xml index 04cd337..77357ba 100644 --- a/gateway/pom.xml +++ b/gateway/pom.xml @@ -20,6 +20,18 @@ spring-boot-starter + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + 1.8.6 + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + 2021.0.4.0 + + org.springframework.boot spring-boot-starter-test @@ -31,6 +43,20 @@ spring-cloud-starter-gateway 3.1.4 + + org.springframework + spring-webmvc + + + org.springframework + spring-webmvc + + + com.alibaba.csp + sentinel-api-gateway-adapter-common + 1.8.6 + compile + diff --git a/gateway/src/main/java/cc/bnblogs/gateway/GatewayApplication.java b/gateway/src/main/java/cc/bnblogs/gateway/GatewayApplication.java index b7a2579..98d6b3d 100644 --- a/gateway/src/main/java/cc/bnblogs/gateway/GatewayApplication.java +++ b/gateway/src/main/java/cc/bnblogs/gateway/GatewayApplication.java @@ -2,6 +2,8 @@ package cc.bnblogs.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.http.codec.ServerCodecConfigurer; @SpringBootApplication public class GatewayApplication { @@ -9,5 +11,4 @@ public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } - } diff --git a/gateway/src/main/java/cc/bnblogs/gateway/config/SentinelRouteConfiguration.java b/gateway/src/main/java/cc/bnblogs/gateway/config/SentinelRouteConfiguration.java new file mode 100644 index 0000000..a3df003 --- /dev/null +++ b/gateway/src/main/java/cc/bnblogs/gateway/config/SentinelRouteConfiguration.java @@ -0,0 +1,108 @@ +package cc.bnblogs.gateway.config; + +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.GatewayRuleManager; +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.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.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import javax.annotation.PostConstruct; +import java.util.*; + +/** + * 限流规则 + */ +@Configuration // 标记为配置类 +public class SentinelRouteConfiguration { // 添加分组api限流 + private final List viewResolvers; + private final ServerCodecConfigurer serverCodecConfigurer; + + public SentinelRouteConfiguration(ObjectProvider> viewResolversProvider, // 构造函数 + ServerCodecConfigurer serverCodecConfigurer) { + this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); + this.serverCodecConfigurer = serverCodecConfigurer; + } + + @PostConstruct + public void initGatewayRules() { + //初始化限流规则 + Set rules = new HashSet<>(); + // 路由限流 + GatewayFlowRule gatewayFlowRule = new GatewayFlowRule("provider_router");// 资源名称,对应routeId的值 此处限流用户服务 + gatewayFlowRule.setCount(1); // 限流阀值 + gatewayFlowRule.setIntervalSec(10); // 统计时间窗口(单位:秒),默认是1秒 +// rules.add(gatewayFlowRule); //为了测试分组限流,先把这个注释 + + // 定义两个api分组 + // 加入分组限流 + rules.add(new GatewayFlowRule("provider_api1").setCount(1).setIntervalSec(1)); + rules.add(new GatewayFlowRule("provider_api2").setCount(1).setIntervalSec(1)); + + GatewayRuleManager.loadRules(rules); // 载入规则 + } + + //自定义API分组 + @PostConstruct + private void initCustomizedApis() { + Set definitions = new HashSet<>(); + ApiDefinition api1 = new ApiDefinition("provider_api1") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/provider/api1/**") // api1下所有接口均被限流 + .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); + }}); + ApiDefinition api2 = new ApiDefinition("provider_api2") + .setPredicateItems(new HashSet() {{ + add(new ApiPathPredicateItem().setPattern("/provider/api2/demo2")); // api2只对demo2接口限流 + }}); + definitions.add(api1); + definitions.add(api2); + GatewayApiDefinitionManager.loadApiDefinitions(definitions); + } + + @PostConstruct + public void initBlockHandlers() { // 自定义限流后的界面 + BlockRequestHandler blockRequestHandler = new BlockRequestHandler() { + @Override + public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { + Map result = new HashMap<>(); // 限流提示 + result.put("code", "0"); + result.put("message", "您已被限流"); + return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON_UTF8). + body(BodyInserters.fromObject(result)); + } + }; + GatewayCallbackManager.setBlockHandler(blockRequestHandler); + } + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { // 配置限流异常处理器 + return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); + } + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public GlobalFilter sentinelGatewayFilter() { //初始化一个限流的过滤器 + return new SentinelGatewayFilter(); + } +} \ No newline at end of file diff --git a/gateway/src/main/resources/application.yml b/gateway/src/main/resources/application.yml index 6441ef8..a84ae72 100644 --- a/gateway/src/main/resources/application.yml +++ b/gateway/src/main/resources/application.yml @@ -8,10 +8,14 @@ spring: discovery: locator: enabled: true - routes: - - id: provider_router - uri: localhost:8080 - predicates: - - Path=/provider/** - filters: - - StripPrefix=1 + nacos: + discovery: + server-addr: localhost:8848 + service: gateway +# routes: +# - id: provider_router +# uri: http://localhost:8080 +# predicates: +# - Path=/provider/** +# filters: +# - StripPrefix=1 diff --git a/provider/pom.xml b/provider/pom.xml index 065b23f..0761d96 100644 --- a/provider/pom.xml +++ b/provider/pom.xml @@ -61,6 +61,12 @@ org.springframework.boot spring-boot-starter-actuator + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + 1.8.6 + compile + diff --git a/provider/src/main/java/cc/bnblogs/provider/controller/IndexController.java b/provider/src/main/java/cc/bnblogs/provider/controller/IndexController.java index b8a4040..4c7d3dc 100644 --- a/provider/src/main/java/cc/bnblogs/provider/controller/IndexController.java +++ b/provider/src/main/java/cc/bnblogs/provider/controller/IndexController.java @@ -62,4 +62,24 @@ public class IndexController { rocketMQTemplate.convertAndSend("orderTopic",order); return order; } + + @GetMapping("/api1/demo1") + public String demo1(){ + return "api1/demo1"; + } + + @GetMapping("/api1/demo2") + public String demo2(){ + return "api1/demo2"; + } + + @GetMapping("/api2/demo1") + public String demo3(){ + return "api2/demo1"; + } + + @GetMapping("/api2/demo2") + public String demo4(){ + return "api2/demo2"; + } }