Commit 56dc8b97069ab886cf07b03225db319f857bf8c0

Authored by zhangdaiscott
1 parent f64a4cff

【新版发布3.2.0】 升级springboot2.6.6、spring-cloud-alibaba 2021.1,深度重构了gateway默认采用sentinal限流熔断降级

Showing 21 changed files with 423 additions and 254 deletions
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/Dockerfile
... ... @@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-gateway
10 10  
11 11 EXPOSE 9999
12 12  
13   -ADD ./target/jeecg-cloud-gateway-3.1.0.jar ./
  13 +ADD ./target/jeecg-cloud-gateway-3.2.0.jar ./
14 14  
15   -CMD sleep 50;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.1.0.jar
16 15 \ No newline at end of file
  16 +CMD sleep 50;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.2.0.jar
17 17 \ No newline at end of file
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/pom.xml
... ... @@ -5,11 +5,11 @@
5 5 <parent>
6 6 <artifactId>jeecg-cloud-module</artifactId>
7 7 <groupId>org.jeecgframework.boot</groupId>
8   - <version>3.1.0</version>
  8 + <version>3.2.0</version>
9 9 </parent>
10 10 <modelVersion>4.0.0</modelVersion>
11   -
12 11 <artifactId>jeecg-cloud-gateway</artifactId>
  12 +
13 13 <dependencies>
14 14 <!-- jeecg 微服务基础依赖-->
15 15 <dependency>
... ... @@ -22,12 +22,22 @@
22 22 </exclusion>
23 23 </exclusions>
24 24 </dependency>
25   - <!-- spring-cloud网关-->
  25 + <!-- Gateway网关依赖,内置webflux-->
26 26 <dependency>
27 27 <groupId>org.springframework.cloud</groupId>
28 28 <artifactId>spring-cloud-starter-gateway</artifactId>
29 29 </dependency>
30   - <!--sentinel断路器依赖-->
  30 + <dependency>
  31 + <groupId>javax.servlet</groupId>
  32 + <artifactId>javax.servlet-api</artifactId>
  33 + </dependency>
  34 + <!-- redis方式限流 -->
  35 + <dependency>
  36 + <groupId>org.springframework.boot</groupId>
  37 + <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
  38 + </dependency>
  39 +
  40 + <!--sentinel 限流熔点降级-->
31 41 <dependency>
32 42 <groupId>com.alibaba.cloud</groupId>
33 43 <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
... ... @@ -36,46 +46,24 @@
36 46 <groupId>com.alibaba.cloud</groupId>
37 47 <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
38 48 </dependency>
  49 + <!-- sentinel集成nacos作为数据源 -->
39 50 <dependency>
40 51 <groupId>com.alibaba.csp</groupId>
41   - <artifactId>sentinel-web-servlet</artifactId>
42   - </dependency>
43   - <!--Spring Webflux-->
44   - <dependency>
45   - <groupId>org.springframework.boot</groupId>
46   - <artifactId>spring-boot-starter-webflux</artifactId>
47   - </dependency>
48   - <!-- 熔断、降级 -->
49   - <dependency>
50   - <groupId>org.springframework.cloud</groupId>
51   - <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  52 + <artifactId>sentinel-datasource-nacos</artifactId>
52 53 </dependency>
  54 + <!--- sentinel流控链路不生效 -->
53 55 <dependency>
54   - <groupId>com.alibaba.cloud</groupId>
55   - <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  56 + <groupId>com.alibaba.csp</groupId>
  57 + <artifactId>sentinel-web-servlet</artifactId>
56 58 </dependency>
  59 +
  60 +
57 61 <!--健康监控-->
58 62 <dependency>
59 63 <groupId>org.springframework.boot</groupId>
60 64 <artifactId>spring-boot-starter-actuator</artifactId>
61 65 </dependency>
62 66  
63   - <!-- 限流Redis实现 -->
64   - <dependency>
65   - <groupId>org.springframework.boot</groupId>
66   - <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
67   - </dependency>
68   - <!--springboot2.X默认使用lettuce连接池,需要引入commons-pool2-->
69   - <dependency>
70   - <groupId>org.apache.commons</groupId>
71   - <artifactId>commons-pool2</artifactId>
72   - </dependency>
73   - <!--server-api-->
74   - <dependency>
75   - <groupId>javax.servlet</groupId>
76   - <artifactId>javax.servlet-api</artifactId>
77   - </dependency>
78   -
79 67 <!-- Swagger API文档 -->
80 68 <dependency>
81 69 <groupId>com.github.xiaoymin</groupId>
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/JeecgGatewayApplication.java
1 1 package org.jeecg;
2 2  
3 3 import org.jeecg.loader.DynamicRouteLoader;
4   -import org.springframework.beans.factory.annotation.Autowired;
5 4 import org.springframework.boot.CommandLineRunner;
6 5 import org.springframework.boot.SpringApplication;
7 6 import org.springframework.boot.autoconfigure.SpringBootApplication;
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/config/GatewayRoutersConfiguration.java
1 1 package org.jeecg.config;
2 2  
3 3 import lombok.extern.slf4j.Slf4j;
4   -import org.jeecg.handler.HystrixFallbackHandler;
5 4 import org.springframework.beans.factory.annotation.Value;
6   -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7 5 import org.springframework.context.annotation.Bean;
8 6 import org.springframework.context.annotation.Configuration;
9 7 import org.springframework.http.MediaType;
10   -import org.springframework.web.reactive.function.server.RequestPredicates;
11 8 import org.springframework.web.reactive.function.server.RouterFunction;
12   -import org.springframework.web.reactive.function.server.RouterFunctions;
13 9 import org.springframework.web.reactive.function.server.ServerResponse;
14 10  
15   -import javax.annotation.Resource;
16   -
17 11 import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
18 12 import static org.springframework.web.reactive.function.server.RouterFunctions.route;
19 13 import static org.springframework.web.reactive.function.server.ServerResponse.ok;
... ... @@ -26,26 +20,18 @@ import static org.springframework.web.reactive.function.server.ServerResponse.ok
26 20 @Slf4j
27 21 @Configuration
28 22 public class GatewayRoutersConfiguration {
29   -
  23 + /**
  24 + * 路由配置方式:database,yml,nacos
  25 + */
  26 + public static String DATA_TYPE;
30 27 public static final long DEFAULT_TIMEOUT = 30000;
31   -
32 28 public static String SERVER_ADDR;
33   -
34 29 public static String NAMESPACE;
35   -
36 30 public static String DATA_ID;
37   -
38 31 public static String ROUTE_GROUP;
39   -
40 32 public static String USERNAME;
41   -
42 33 public static String PASSWORD;
43 34  
44   - /**
45   - * 路由配置文件数据获取方式yml,nacos,database
46   - */
47   - public static String DATA_TYPE;
48   -
49 35 @Value("${spring.cloud.nacos.discovery.server-addr}")
50 36 public void setServerAddr(String serverAddr) {
51 37 SERVER_ADDR = serverAddr;
... ... @@ -66,13 +52,16 @@ public class GatewayRoutersConfiguration {
66 52 ROUTE_GROUP = routeGroup;
67 53 }
68 54  
69   - @Value("${jeecg.route.config.data-type}")
70   - public void setDataType(String dataType) { DATA_TYPE = dataType; }
  55 + @Value("${jeecg.route.config.data-type:#{null}}")
  56 + public void setDataType(String dataType) {
  57 + DATA_TYPE = dataType;
  58 + }
71 59  
72 60 @Value("${spring.cloud.nacos.config.username}")
73 61 public void setUsername(String username) {
74 62 USERNAME = username;
75 63 }
  64 +
76 65 @Value("${spring.cloud.nacos.config.password}")
77 66 public void setPassword(String password) {
78 67 PASSWORD = password;
... ... @@ -80,18 +69,8 @@ public class GatewayRoutersConfiguration {
80 69  
81 70  
82 71 /**
83   - * 路由断言
84   - * @return
85   - */
86   - @Bean
87   - public RouterFunction routerFunction() {
88   - return RouterFunctions.route(
89   - RequestPredicates.path("/globalFallback").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler);
90   -
91   - }
92   -
93   - /**
94   - * 映射接口文档默认地址(通过9999端口直接访问)
  72 + * 接口地址(通过9999端口直接访问)
  73 + *
95 74 * @param indexHtml
96 75 * @return
97 76 */
... ... @@ -100,7 +79,4 @@ public class GatewayRoutersConfiguration {
100 79 return route(GET("/"), request -> ok().contentType(MediaType.TEXT_HTML).syncBody(indexHtml));
101 80 }
102 81  
103   - @Resource
104   - private HystrixFallbackHandler hystrixFallbackHandler;
105   -
106 82 }
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/fallback/FallbackController.java
1   -package org.jeecg.fallback;
2   -
3   -import org.springframework.web.bind.annotation.RequestMapping;
4   -import org.springframework.web.bind.annotation.RestController;
5   -import reactor.core.publisher.Mono;
6   -
7   -/**
8   - * 响应超时熔断处理器
9   - *
10   - * @author zyf
11   - */
12   -@RestController
13   -public class FallbackController {
14   -
15   - /**
16   - * 全局熔断处理
17   - * @return
18   - */
19   - @RequestMapping("/fallback")
20   - public Mono<String> fallback() {
21   - return Mono.just("访问超时,请稍后再试!");
22   - }
23   -
24   - /**
25   - * demo熔断处理
26   - * @return
27   - */
28   - @RequestMapping("/demo/fallback")
29   - public Mono<String> fallback2() {
30   - return Mono.just("访问超时,请稍后再试!");
31   - }
32   -}
  1 +//package org.jeecg.fallback;
  2 +//
  3 +//import org.springframework.web.bind.annotation.RequestMapping;
  4 +//import org.springframework.web.bind.annotation.RestController;
  5 +//import reactor.core.publisher.Mono;
  6 +//
  7 +///**
  8 +// * 响应超时熔断处理器【升级springboot2.6.6后,此类作废】
  9 +// *
  10 +// * @author zyf
  11 +// */
  12 +//@RestController
  13 +//public class FallbackController {
  14 +//
  15 +// /**
  16 +// * 全局熔断处理
  17 +// * @return
  18 +// */
  19 +// @RequestMapping("/fallback")
  20 +// public Mono<String> fallback() {
  21 +// return Mono.just("访问超时,请稍后再试!");
  22 +// }
  23 +//
  24 +// /**
  25 +// * demo熔断处理
  26 +// * @return
  27 +// */
  28 +// @RequestMapping("/demo/fallback")
  29 +// public Mono<String> fallback2() {
  30 +// return Mono.just("访问超时,请稍后再试!");
  31 +// }
  32 +//}
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/fallback/HystrixFallbackHandler.java 0 → 100644
  1 +//package org.jeecg.fallback;
  2 +//
  3 +//import lombok.extern.slf4j.Slf4j;
  4 +//import org.springframework.http.HttpStatus;
  5 +//import org.springframework.stereotype.Component;
  6 +//import org.springframework.web.reactive.function.BodyInserters;
  7 +//import org.springframework.web.reactive.function.server.HandlerFunction;
  8 +//import org.springframework.web.reactive.function.server.ServerRequest;
  9 +//import org.springframework.web.reactive.function.server.ServerResponse;
  10 +//import reactor.core.publisher.Mono;
  11 +//
  12 +//import java.util.Optional;
  13 +//
  14 +//import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
  15 +//
  16 +///**
  17 +// * @author scott
  18 +// * @date 2020/05/26
  19 +// * Hystrix 降级处理
  20 +// */
  21 +//@Slf4j
  22 +//@Component
  23 +//public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
  24 +// @Override
  25 +// public Mono<ServerResponse> handle(ServerRequest serverRequest) {
  26 +// Optional<Object> originalUris = serverRequest.attribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
  27 +//
  28 +// originalUris.ifPresent(originalUri -> log.error("网关执行请求:{}失败,hystrix服务降级处理", originalUri));
  29 +//
  30 +// return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
  31 +// .header("Content-Type","text/plain; charset=utf-8").body(BodyInserters.fromObject("访问超时,请稍后再试"));
  32 +// }
  33 +//}
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/fallback/sentinel/GatewaySentinelExceptionConfig.java 0 → 100644
  1 +package org.jeecg.fallback.sentinel;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
  5 +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
  6 +import org.jeecg.common.enums.SentinelErrorInfoEnum;
  7 +import org.springframework.context.annotation.Configuration;
  8 +import org.springframework.http.HttpStatus;
  9 +import org.springframework.http.MediaType;
  10 +import org.springframework.web.reactive.function.BodyInserters;
  11 +import org.springframework.web.reactive.function.server.ServerResponse;
  12 +
  13 +import javax.annotation.PostConstruct;
  14 +import java.util.HashMap;
  15 +
  16 +/**
  17 + * @Description: 自定义Sentinel全局异常(需要启动Sentinel客户端)
  18 + * @author: zyf
  19 + * @date: 2022/02/18
  20 + * @version: V1.0
  21 + */
  22 +@Configuration
  23 +public class GatewaySentinelExceptionConfig {
  24 +
  25 + @PostConstruct
  26 + public void init() {
  27 +
  28 + BlockRequestHandler blockRequestHandler = (serverWebExchange, ex) -> {
  29 + String msg;
  30 + SentinelErrorInfoEnum errorInfoEnum = SentinelErrorInfoEnum.getErrorByException(ex);
  31 + if (ObjectUtil.isNotEmpty(errorInfoEnum)) {
  32 + msg = errorInfoEnum.getError();
  33 + } else {
  34 + msg = "未知限流降级";
  35 + }
  36 + HashMap<String, String> map = new HashMap();
  37 + map.put("code", HttpStatus.TOO_MANY_REQUESTS.toString());
  38 + map.put("message", msg);
  39 + //自定义异常处理
  40 + return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));
  41 + };
  42 +
  43 + GatewayCallbackManager.setBlockHandler(blockRequestHandler);
  44 + }
  45 +}
0 46 \ No newline at end of file
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/fallback/sentinel/SentinelBlockRequestHandler.java 0 → 100644
  1 +//package org.jeecg.fallback.sentinel;
  2 +//import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
  3 +//import com.alibaba.csp.sentinel.transport.config.TransportConfig;
  4 +//import lombok.extern.slf4j.Slf4j;
  5 +//import org.springframework.beans.factory.annotation.Autowired;
  6 +//import org.springframework.cloud.commons.util.InetUtils;
  7 +//import org.springframework.http.HttpStatus;
  8 +//import org.springframework.http.MediaType;
  9 +//import org.springframework.stereotype.Component;
  10 +//import org.springframework.web.reactive.function.BodyInserters;
  11 +//import org.springframework.web.reactive.function.server.ServerResponse;
  12 +//import org.springframework.web.server.ServerWebExchange;
  13 +//import reactor.core.publisher.Mono;
  14 +//
  15 +//import javax.annotation.PostConstruct;
  16 +//
  17 +///**
  18 +// * 自定义限流返回信息
  19 +// * @author scott
  20 +// */
  21 +//@Slf4j
  22 +//@Component
  23 +//public class SentinelBlockRequestHandler implements BlockRequestHandler {
  24 +// @Autowired
  25 +// private InetUtils inetUtils;
  26 +//
  27 +// @PostConstruct
  28 +// public void doInit() {
  29 +// System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
  30 +// }
  31 +//
  32 +// @Override
  33 +// public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
  34 +// String resultString = "{\"code\":403,\"message\":\"服务开启限流保护,请稍后再试!\"}";
  35 +// return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(resultString));
  36 +// }
  37 +//
  38 +//
  39 +//}
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/filter/GlobalAccessTokenFilter.java
... ... @@ -15,8 +15,13 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
15 15 import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
16 16  
17 17 /**
18   - *
19   - */
  18 +* 全局拦截器,作用所有的微服务
  19 +*
  20 +* 1.重写StripPrefix(获取真实的URL)
  21 +* 2.将现在的request,添加当前身份
  22 +* @author: scott
  23 +* @date: 2022/4/8 10:55
  24 +*/
20 25 @Slf4j
21 26 @Component
22 27 public class GlobalAccessTokenFilter implements GlobalFilter, Ordered {
... ... @@ -41,7 +46,7 @@ public class GlobalAccessTokenFilter implements GlobalFilter, Ordered {
41 46 ServerHttpRequest newRequest = exchange.getRequest().mutate().path(newPath).build();
42 47 exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
43 48  
44   - //将现在的request,添加当前身份
  49 + //2.将现在的request,添加当前身份
45 50 ServerHttpRequest mutableReq = exchange.getRequest().mutate().header("Authorization-UserName", "").header(X_GATEWAY_BASE_PATH,basePath).build();
46 51 ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
47 52 return chain.filter(mutableExchange);
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/filter/SentinelFilterContextConfig.java
... ... @@ -6,7 +6,8 @@ import org.springframework.context.annotation.Bean;
6 6 import org.springframework.context.annotation.Configuration;
7 7  
8 8 /**
9   - * @author Administrator
  9 + * @author: zyf
  10 + * @date: 20210715
10 11 */
11 12 @Configuration
12 13 public class SentinelFilterContextConfig {
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/HystrixFallbackHandler.java deleted
1   -package org.jeecg.handler;
2   -
3   -import lombok.extern.slf4j.Slf4j;
4   -import org.springframework.http.HttpStatus;
5   -import org.springframework.http.MediaType;
6   -import org.springframework.stereotype.Component;
7   -import org.springframework.web.reactive.function.BodyInserters;
8   -import org.springframework.web.reactive.function.server.HandlerFunction;
9   -import org.springframework.web.reactive.function.server.ServerRequest;
10   -import org.springframework.web.reactive.function.server.ServerResponse;
11   -import reactor.core.publisher.Mono;
12   -
13   -import java.util.Optional;
14   -
15   -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
16   -
17   -/**
18   - * @author scott
19   - * @date 2020/05/26
20   - * Hystrix 降级处理
21   - */
22   -@Slf4j
23   -@Component
24   -public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
25   - @Override
26   - public Mono<ServerResponse> handle(ServerRequest serverRequest) {
27   - Optional<Object> originalUris = serverRequest.attribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
28   -
29   - originalUris.ifPresent(originalUri -> log.error("网关执行请求:{}失败,hystrix服务降级处理", originalUri));
30   -
31   - return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
32   - .header("Content-Type","text/plain; charset=utf-8").body(BodyInserters.fromObject("访问超时,请稍后再试"));
33   - }
34   -}
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/LoderRouderHandler.java
... ... @@ -2,18 +2,19 @@ package org.jeecg.handler;
2 2  
3 3 import lombok.extern.slf4j.Slf4j;
4 4 import org.jeecg.common.base.BaseMap;
5   -import org.jeecg.common.modules.redis.listener.JeecgRedisListerer;
  5 +import org.jeecg.common.constant.GlobalConstants;
  6 +import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
6 7 import org.jeecg.loader.DynamicRouteLoader;
7 8 import org.springframework.stereotype.Component;
8 9  
9 10 import javax.annotation.Resource;
10 11  
11 12 /**
12   - * 路由刷新监听
  13 + * 路由刷新监听(实现方式:redis监听handler)
13 14 */
14 15 @Slf4j
15   -@Component
16   -public class LoderRouderHandler implements JeecgRedisListerer {
  16 +@Component(GlobalConstants.LODER_ROUDER_HANDLER)
  17 +public class LoderRouderHandler implements JeecgRedisListener {
17 18  
18 19 @Resource
19 20 private DynamicRouteLoader dynamicRouteLoader;
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/SentinelBlockRequestHandler.java deleted
1   -package org.jeecg.handler;
2   -import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
3   -import com.alibaba.csp.sentinel.transport.config.TransportConfig;
4   -import lombok.extern.slf4j.Slf4j;
5   -import org.springframework.beans.factory.annotation.Autowired;
6   -import org.springframework.cloud.commons.util.InetUtils;
7   -import org.springframework.http.HttpStatus;
8   -import org.springframework.http.MediaType;
9   -import org.springframework.stereotype.Component;
10   -import org.springframework.web.reactive.function.BodyInserters;
11   -import org.springframework.web.reactive.function.server.ServerResponse;
12   -import org.springframework.web.server.ServerWebExchange;
13   -import reactor.core.publisher.Mono;
14   -
15   -import javax.annotation.PostConstruct;
16   -
17   -/**
18   - * 自定义限流返回信息
19   - * @author Administrator
20   - */
21   -@Slf4j
22   -@Component
23   -public class SentinelBlockRequestHandler implements BlockRequestHandler {
24   - @Autowired
25   - private InetUtils inetUtils;
26   -
27   - @PostConstruct
28   - public void doInit() {
29   - System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
30   - }
31   -
32   - @Override
33   - public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
34   - String resultString = "{\"code\":403,\"message\":\"服务开启限流保护,请稍后再试!\"}";
35   - return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(resultString));
36   - }
37   -
38   -}
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/MySwaggerResourceProvider.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/MySwaggerResourceProvider.java
1   -package org.jeecg.handler;
2   -
3   -import java.util.ArrayList;
4   -import java.util.HashSet;
5   -import java.util.List;
6   -import java.util.Set;
  1 +package org.jeecg.handler.swagger;
7 2  
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.alibaba.nacos.api.naming.NamingFactory;
  5 +import com.alibaba.nacos.api.naming.NamingService;
  6 +import com.alibaba.nacos.api.naming.pojo.Instance;
  7 +import lombok.extern.slf4j.Slf4j;
8 8 import org.springframework.beans.factory.annotation.Autowired;
9 9 import org.springframework.beans.factory.annotation.Value;
10 10 import org.springframework.cloud.gateway.route.RouteLocator;
11 11 import org.springframework.context.annotation.Primary;
12 12 import org.springframework.stereotype.Component;
13 13  
14   -import lombok.extern.slf4j.Slf4j;
15 14 import springfox.documentation.swagger.web.SwaggerResource;
16 15 import springfox.documentation.swagger.web.SwaggerResourcesProvider;
17 16  
  17 +import java.util.ArrayList;
  18 +import java.util.HashSet;
  19 +import java.util.List;
  20 +import java.util.Set;
  21 +
18 22 /**
19 23 * 聚合各个服务的swagger接口
20 24 */
... ... @@ -33,6 +37,13 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
33 37 private final RouteLocator routeLocator;
34 38  
35 39 /**
  40 + * nacos服务地址
  41 + */
  42 + @Value("${spring.cloud.nacos.discovery.server-addr}")
  43 + private String serverAddr;
  44 +
  45 +
  46 + /**
36 47 * 网关应用名称
37 48 */
38 49 @Value("${spring.application.name}")
... ... @@ -50,7 +61,14 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
50 61 // 获取所有可用的host:serviceId
51 62 routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
52 63 .filter(route -> !self.equals(route.getUri().getHost()))
53   - .subscribe(route -> routeHosts.add(route.getUri().getHost()));
  64 + .subscribe(route ->{
  65 + //update-begin---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开
  66 + boolean hasRoute=checkRoute(route.getId());
  67 + if(hasRoute){
  68 + routeHosts.add(route.getUri().getHost());
  69 + }
  70 + //update-end---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开
  71 + });
54 72  
55 73 // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上
56 74 Set<String> dealed = new HashSet<>();
... ... @@ -72,4 +90,23 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
72 90 });
73 91 return resources;
74 92 }
  93 +
  94 + /**
  95 + * 检测nacos中是否有健康实例
  96 + * @param routeId
  97 + * @return
  98 + */
  99 + private Boolean checkRoute(String routeId) {
  100 + Boolean hasRoute = false;
  101 + try {
  102 + NamingService naming = NamingFactory.createNamingService(serverAddr);
  103 + List<Instance> list = naming.selectInstances(routeId, true);
  104 + if (ObjectUtil.isNotEmpty(list)) {
  105 + hasRoute = true;
  106 + }
  107 + } catch (Exception e) {
  108 + e.printStackTrace();
  109 + }
  110 + return hasRoute;
  111 + }
75 112 }
76 113 \ No newline at end of file
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/SwaggerResourceController.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java
1   -package org.jeecg.handler;
  1 +package org.jeecg.handler.swagger;
2 2  
3 3 import org.springframework.beans.factory.annotation.Autowired;
4 4 import org.springframework.http.HttpStatus;
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/DynamicRouteLoader.java
... ... @@ -10,17 +10,19 @@ import com.alibaba.nacos.api.config.listener.Listener;
10 10 import com.alibaba.nacos.api.exception.NacosException;
11 11 import com.google.common.collect.Lists;
12 12 import lombok.extern.slf4j.Slf4j;
13   -import org.apache.commons.lang.StringUtils;
14 13 import org.apache.commons.lang3.ObjectUtils;
  14 +import org.apache.commons.lang3.StringUtils;
15 15 import org.jeecg.common.base.BaseMap;
16 16 import org.jeecg.common.constant.CacheConstant;
17 17 import org.jeecg.common.util.RedisUtil;
18 18 import org.jeecg.config.GatewayRoutersConfiguration;
19 19 import org.jeecg.config.RouterDataType;
  20 +import org.jeecg.loader.repository.DynamicRouteService;
  21 +import org.jeecg.loader.repository.MyInMemoryRouteDefinitionRepository;
  22 +import org.jeecg.loader.vo.MyRouteDefinition;
20 23 import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
21 24 import org.springframework.cloud.gateway.filter.FilterDefinition;
22 25 import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
23   -import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
24 26 import org.springframework.cloud.gateway.route.RouteDefinition;
25 27 import org.springframework.context.ApplicationEventPublisher;
26 28 import org.springframework.context.ApplicationEventPublisherAware;
... ... @@ -48,28 +50,26 @@ import java.util.concurrent.Executor;
48 50 public class DynamicRouteLoader implements ApplicationEventPublisherAware {
49 51  
50 52  
  53 + private MyInMemoryRouteDefinitionRepository repository;
51 54 private ApplicationEventPublisher publisher;
52   -
53   - private InMemoryRouteDefinitionRepository repository;
54   -
55 55 private DynamicRouteService dynamicRouteService;
56   -
57 56 private ConfigService configService;
58   -
59 57 private RedisUtil redisUtil;
60 58  
61 59  
62   - public DynamicRouteLoader(InMemoryRouteDefinitionRepository repository, DynamicRouteService dynamicRouteService, RedisUtil redisUtil) {
  60 + public DynamicRouteLoader(MyInMemoryRouteDefinitionRepository repository, DynamicRouteService dynamicRouteService, RedisUtil redisUtil) {
63 61  
64 62 this.repository = repository;
65 63 this.dynamicRouteService = dynamicRouteService;
66 64 this.redisUtil = redisUtil;
67 65 }
68 66  
69   - @PostConstruct
70   - public void init() {
71   - init(null);
72   - }
  67 +// @PostConstruct
  68 +// public void init() {
  69 +// init(null);
  70 +// }
  71 +
  72 +
73 73 public void init(BaseMap baseMap) {
74 74 String dataType = GatewayRoutersConfiguration.DATA_TYPE;
75 75 log.info("初始化路由,dataType:"+ dataType);
... ... @@ -138,7 +138,7 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
138 138 }
139 139 Object configInfo = redisUtil.get(CacheConstant.GATEWAY_ROUTES);
140 140 if (ObjectUtil.isNotEmpty(configInfo)) {
141   - log.info("获取网关当前配置:\r\n{}", configInfo);
  141 + log.debug("获取网关当前配置:\r\n{}", configInfo);
142 142 JSONArray array = JSON.parseArray(configInfo.toString());
143 143 try {
144 144 routes = getRoutesByJson(array);
... ... @@ -147,7 +147,7 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
147 147 }
148 148 }
149 149 for (MyRouteDefinition definition : routes) {
150   - log.info("update route : {}", definition.toString());
  150 + log.debug("update route : {}", definition.toString());
151 151 Integer status=definition.getStatus();
152 152 if(status.equals(0)){
153 153 dynamicRouteService.delete(definition.getId());
... ... @@ -156,9 +156,9 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
156 156 }
157 157 }
158 158 if(ObjectUtils.isNotEmpty(baseMap)){
159   - String routerId=baseMap.get("routerId");
160   - if(ObjectUtils.isNotEmpty(routerId)) {
161   - dynamicRouteService.delete(routerId);
  159 + String delRouterId = baseMap.get("delRouterId");
  160 + if (ObjectUtils.isNotEmpty(delRouterId)) {
  161 + dynamicRouteService.delete(delRouterId);
162 162 }
163 163 }
164 164 this.publisher.publishEvent(new RefreshRoutesEvent(this));
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/DynamicRouteService.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/repository/DynamicRouteService.java
1   -package org.jeecg.loader;
  1 +package org.jeecg.loader.repository;
2 2  
3 3 import lombok.extern.slf4j.Slf4j;
  4 +import org.jeecg.loader.repository.MyInMemoryRouteDefinitionRepository;
4 5 import org.springframework.beans.factory.annotation.Autowired;
5 6 import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
6   -import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
7 7 import org.springframework.cloud.gateway.route.RouteDefinition;
8   -import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
9   -import org.springframework.cloud.gateway.support.NotFoundException;
10 8 import org.springframework.context.ApplicationEventPublisher;
11 9 import org.springframework.context.ApplicationEventPublisherAware;
12   -import org.springframework.http.ResponseEntity;
13 10 import org.springframework.stereotype.Service;
14 11 import reactor.core.publisher.Mono;
15 12  
... ... @@ -25,10 +22,7 @@ import reactor.core.publisher.Mono;
25 22 public class DynamicRouteService implements ApplicationEventPublisherAware {
26 23  
27 24 @Autowired
28   - private RouteDefinitionWriter routeDefinitionWriter;
29   -
30   - @Autowired
31   - private InMemoryRouteDefinitionRepository repository;
  25 + private MyInMemoryRouteDefinitionRepository repository;
32 26  
33 27 /**
34 28 * 发布事件
... ... @@ -52,7 +46,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
52 46 repository.delete(Mono.just(id)).subscribe();
53 47 this.publisher.publishEvent(new RefreshRoutesEvent(this));
54 48 }catch (Exception e){
55   - //e.printStackTrace();
  49 + log.warn(e.getMessage(),e);
56 50 }
57 51 }
58 52  
... ... @@ -89,7 +83,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
89 83 try {
90 84 repository.save(Mono.just(definition)).subscribe();
91 85 } catch (Exception e) {
92   -
  86 + log.warn(e.getMessage(),e);
93 87 }
94 88 return "success";
95 89 }
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/repository/MyInMemoryRouteDefinitionRepository.java 0 → 100644
  1 +//
  2 +// Source code recreated from a .class file by IntelliJ IDEA
  3 +// (powered by Fernflower decompiler)
  4 +//
  5 +
  6 +package org.jeecg.loader.repository;
  7 +
  8 +import java.util.Collections;
  9 +import java.util.LinkedHashMap;
  10 +import java.util.Map;
  11 +import java.util.function.Function;
  12 +import java.util.function.Supplier;
  13 +
  14 +import ch.qos.logback.classic.Logger;
  15 +import lombok.extern.slf4j.Slf4j;
  16 +import org.springframework.cloud.gateway.route.RouteDefinition;
  17 +import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
  18 +import org.springframework.cloud.gateway.support.NotFoundException;
  19 +import org.springframework.stereotype.Component;
  20 +import org.springframework.util.ObjectUtils;
  21 +import reactor.core.publisher.Flux;
  22 +import reactor.core.publisher.Mono;
  23 +
  24 +/**
  25 + * @author qinfeng
  26 + */
  27 +@Slf4j
  28 +@Component
  29 +public class MyInMemoryRouteDefinitionRepository implements RouteDefinitionRepository {
  30 + private final Map<String, RouteDefinition> routes = Collections.synchronizedMap(new LinkedHashMap());
  31 +
  32 + public MyInMemoryRouteDefinitionRepository() {
  33 + }
  34 +
  35 + @Override
  36 + public Mono<Void> save(Mono<RouteDefinition> route) {
  37 + return route.flatMap((r) -> {
  38 + if (ObjectUtils.isEmpty(r.getId())) {
  39 + return Mono.error(new IllegalArgumentException("id may not be empty"));
  40 + } else {
  41 + this.routes.put(r.getId(), r);
  42 + return Mono.empty();
  43 + }
  44 + });
  45 + }
  46 +
  47 + @Override
  48 + public Mono<Void> delete(Mono<String> routeId) {
  49 + return routeId.flatMap((id) -> {
  50 + if (this.routes.containsKey(id)) {
  51 + this.routes.remove(id);
  52 + return Mono.empty();
  53 + } else {
  54 + log.warn("RouteDefinition not found: " + routeId);
  55 + return Mono.empty();
  56 +// return Mono.defer(() -> {
  57 +// return Mono.error(new NotFoundException("RouteDefinition not found: " + routeId));
  58 +// });
  59 + }
  60 + });
  61 + }
  62 +
  63 + @Override
  64 + public Flux<RouteDefinition> getRouteDefinitions() {
  65 + Map<String, RouteDefinition> routesSafeCopy = new LinkedHashMap(this.routes);
  66 + return Flux.fromIterable(routesSafeCopy.values());
  67 + }
  68 +}
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/GatewayRouteVo.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/vo/GatewayRouteVo.java
1   -package org.jeecg.loader;
  1 +package org.jeecg.loader.vo;
2 2  
3 3 import lombok.Data;
4 4  
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/MyRouteDefinition.java renamed to jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/vo/MyRouteDefinition.java
1   -package org.jeecg.loader;
  1 +package org.jeecg.loader.vo;
2 2  
3 3 import org.springframework.cloud.gateway.route.RouteDefinition;
4 4  
... ...
jeecg-boot/jeecg-cloud-module/jeecg-cloud-gateway/src/main/resources/application.yml
... ... @@ -3,14 +3,83 @@ server:
3 3 spring:
4 4 application:
5 5 name: jeecg-gateway
  6 + main:
  7 + #循环依赖默认情况下已经被禁止了
  8 + allow-circular-references: true
  9 + allow-bean-definition-overriding: true
6 10 cloud:
7 11 #Sentinel配置
8 12 sentinel:
9   - web-context-unify: false
10 13 transport:
11   - dashboard: localhost:8087
12   - # 懒加载Sentinel Dashboard菜单
  14 + dashboard: jeecg-boot-sentinel:9000
  15 + # 支持链路限流
  16 + web-context-unify: false
  17 + filter:
  18 + enabled: false
  19 + # 取消Sentinel控制台懒加载
13 20 eager: false
  21 + datasource:
  22 + #流控规则
  23 + flow: # 指定数据源名称
  24 + # 指定nacos数据源
  25 + nacos:
  26 + server-addr: @config.server-addr@
  27 + # 指定配置文件
  28 + dataId: ${spring.application.name}-flow-rules
  29 + # 指定分组
  30 + groupId: SENTINEL_GROUP
  31 + # 指定配置文件规则类型
  32 + rule-type: flow
  33 + # 指定配置文件数据格式
  34 + data-type: json
  35 + #降级规则
  36 + degrade:
  37 + nacos:
  38 + server-addr: @config.server-addr@
  39 + dataId: ${spring.application.name}-degrade-rules
  40 + groupId: SENTINEL_GROUP
  41 + rule-type: degrade
  42 + data-type: json
  43 + #系统规则
  44 + system:
  45 + nacos:
  46 + server-addr: @config.server-addr@
  47 + dataId: ${spring.application.name}-system-rules
  48 + groupId: SENTINEL_GROUP
  49 + rule-type: system
  50 + data-type: json
  51 + #授权规则
  52 + authority:
  53 + nacos:
  54 + server-addr: @config.server-addr@
  55 + dataId: ${spring.application.name}-authority-rules
  56 + groupId: SENTINEL_GROUP
  57 + rule-type: authority
  58 + data-type: json
  59 + #热点参数
  60 + param-flow:
  61 + nacos:
  62 + server-addr: @config.server-addr@
  63 + dataId: ${spring.application.name}-param-rules
  64 + groupId: SENTINEL_GROUP
  65 + rule-type: param-flow
  66 + data-type: json
  67 + #网关流控规则
  68 + gw-flow:
  69 + nacos:
  70 + server-addr: @config.server-addr@
  71 + dataId: ${spring.application.name}-flow-rules
  72 + groupId: SENTINEL_GROUP
  73 + rule-type: gw-flow
  74 + data-type: json
  75 + #API流控规则
  76 + gw-api-group:
  77 + nacos:
  78 + server-addr: @config.server-addr@
  79 + dataId: ${spring.application.name}-api-rules
  80 + groupId: SENTINEL_GROUP
  81 + rule-type: gw-api-group
  82 + data-type: json
14 83 gateway:
15 84 discovery:
16 85 locator:
... ... @@ -19,11 +88,23 @@ spring:
19 88 cors-configurations:
20 89 '[/**]':
21 90 allowCredentials: true
22   - allowedOrigins: "*"
  91 + #springboot2.4后需用allowedOriginPatterns
  92 + allowedOriginPatterns: "*"
23 93 allowedMethods: "*"
24 94 allowedHeaders: "*"
25   -# #如果启用nacos或者数据库配置请删除一下配置
  95 +# httpclient:
  96 +# connect-timeout: 1000
  97 +# response-timeout: 5s
  98 +# # Nacos的yml方式路由配置(默认注释掉,采用数据库加载)
26 99 # routes:
  100 +## - id: jeecg-eoa
  101 +## uri: lb://jeecg-eoa
  102 +## predicates:
  103 +## - Path=/eoa/**,/v1/**,/generic/**
  104 +## - id: jeecg-joa
  105 +## uri: lb://jeecg-joa
  106 +## predicates:
  107 +## - Path=/desflow/**,/joa/**,/desform/**,/act/**,/plug-in/**
27 108 # - id: jeecg-demo
28 109 # uri: lb://jeecg-demo
29 110 # predicates:
... ... @@ -39,30 +120,4 @@ spring:
39 120 # - id: jeecg-demo-websocket
40 121 # uri: lb:ws://jeecg-demo
41 122 # predicates:
42   -# - Path=/vxeSocket/**
43   - # 全局熔断降级配置
44   - default-filters:
45   - - name: Hystrix
46   - args:
47   - name: default
48   - #转发地址
49   - fallbackUri: 'forward:/fallback'
50   - - name: Retry
51   - args:
52   - #重试次数,默认值是 3 次
53   - retries: 3
54   - #HTTP 的状态返回码
55   - statuses: BAD_GATEWAY,BAD_REQUEST
56   - #指定哪些方法的请求需要进行重试逻辑,默认值是 GET 方法
57   - methods: GET,POST
58   -# hystrix 信号量隔离,3秒后自动超时
59   -hystrix:
60   - enabled: true
61   - shareSecurityContext: true
62   - command:
63   - default:
64   - execution:
65   - isolation:
66   - strategy: SEMAPHORE
67   - thread:
68   - timeoutInMilliseconds: 9000
69 123 \ No newline at end of file
  124 +# - Path=/vxeSocket/**
70 125 \ No newline at end of file
... ...