瀏覽代碼

从redis自动加载路由

yufeng0528 4 年之前
父節點
當前提交
3be346b73a

+ 23 - 11
pom.xml

@@ -15,7 +15,7 @@
15 15
 	<parent>
16 16
         <groupId>org.springframework.boot</groupId>
17 17
         <artifactId>spring-boot-starter-parent</artifactId>
18
-        <version>2.2.1.RELEASE</version>
18
+        <version>2.1.4.RELEASE</version>
19 19
         <relativePath />
20 20
     </parent>
21 21
 
@@ -23,7 +23,7 @@
23 23
 		<maven.compiler.source>1.8</maven.compiler.source>
24 24
 		<maven.compiler.target>1.8</maven.compiler.target>
25 25
 		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
26
-		<spring-cloud.version>2.2.0.RELEASE</spring-cloud.version>
26
+		<spring-cloud.version>2.1.4.RELEASE</spring-cloud.version>
27 27
 	</properties>
28 28
 	
29 29
 	<dependencyManagement>
@@ -31,7 +31,7 @@
31 31
             <dependency>
32 32
                 <groupId>org.springframework.cloud</groupId>
33 33
                 <artifactId>spring-cloud-dependencies</artifactId>
34
-                <version>Hoxton.RELEASE</version>
34
+                <version>Greenwich.RELEASE</version>
35 35
                 <type>pom</type>
36 36
                 <scope>import</scope>
37 37
             </dependency>
@@ -57,16 +57,16 @@
57 57
 		</dependency>
58 58
 	
59 59
 		<!-- hystrix -->
60
-<!-- 		<dependency> -->
61
-<!-- 			<groupId>org.springframework.cloud</groupId> -->
62
-<!-- 			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId> -->
63
-<!-- 		</dependency> -->
60
+		<dependency>
61
+			<groupId>org.springframework.cloud</groupId>
62
+			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
63
+		</dependency>
64 64
 		
65 65
 		<!-- 最新推荐的断路器 -->
66
-        <dependency>
67
-            <groupId>org.springframework.cloud</groupId>
68
-            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
69
-        </dependency>
66
+<!--         <dependency> -->
67
+<!--             <groupId>org.springframework.cloud</groupId> -->
68
+<!--             <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> -->
69
+<!--         </dependency> -->
70 70
         
71 71
 		<!-- Spring Boot Web Flux 依赖 -->
72 72
 		<dependency>
@@ -80,6 +80,18 @@
80 80
 			<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
81 81
 		</dependency>
82 82
 		
83
+		<dependency>
84
+            <groupId>com.alicp.jetcache</groupId>
85
+            <artifactId>jetcache-starter-redis</artifactId>
86
+            <version>2.6.0.M3</version>
87
+        </dependency>
88
+
89
+		<dependency>
90
+			<groupId>com.alicp.jetcache</groupId>
91
+			<artifactId>jetcache-redis-lettuce</artifactId>
92
+			<version>2.6.0.M3</version>
93
+		</dependency>
94
+			
83 95
 		<!-- Spring test 依赖 -->
84 96
         <dependency>
85 97
             <groupId>org.springframework.boot</groupId>

+ 4 - 0
src/main/java/com/yaozhitech/spring5/App.java

@@ -4,9 +4,13 @@ import org.springframework.boot.SpringApplication;
4 4
 import org.springframework.boot.autoconfigure.SpringBootApplication;
5 5
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
6 6
 
7
+import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
8
+import com.alicp.jetcache.anno.config.EnableMethodCache;
7 9
 import com.yaozhitech.spring5.config.UriConfiguration;
8 10
 
9 11
 
12
+@EnableMethodCache(basePackages = "com.yaozhitech.spring5")
13
+@EnableCreateCacheAnnotation
10 14
 @EnableConfigurationProperties(UriConfiguration.class)
11 15
 @SpringBootApplication
12 16
 public class App {

+ 1 - 2
src/main/java/com/yaozhitech/spring5/config/RedisConfig.java

@@ -2,7 +2,6 @@ package com.yaozhitech.spring5.config;
2 2
 
3 3
 
4 4
 import org.springframework.cache.annotation.CachingConfigurerSupport;
5
-import org.springframework.cache.annotation.EnableCaching;
6 5
 import org.springframework.context.annotation.Bean;
7 6
 import org.springframework.context.annotation.Configuration;
8 7
 import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
@@ -20,8 +19,8 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
20 19
  * @author yinzy
21 20
  */
22 21
 @Configuration
23
-@EnableCaching
24 22
 public class RedisConfig extends CachingConfigurerSupport {
23
+	
25 24
 	public static String cachePrefix = "bbc:";
26 25
 	
27 26
     @Bean

+ 41 - 0
src/main/java/com/yaozhitech/spring5/config/RedisRouteDefinitionRepository.java

@@ -0,0 +1,41 @@
1
+package com.yaozhitech.spring5.config;
2
+
3
+import org.springframework.beans.factory.annotation.Autowired;
4
+import org.springframework.cloud.gateway.route.RouteDefinition;
5
+import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
6
+import org.springframework.stereotype.Component;
7
+
8
+import com.yaozhitech.spring5.service.RouteService;
9
+
10
+import lombok.extern.slf4j.Slf4j;
11
+import reactor.core.publisher.Flux;
12
+import reactor.core.publisher.Mono;
13
+
14
+@Component
15
+@Slf4j
16
+public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
17
+
18
+    @Autowired
19
+    private RouteService routeService;
20
+
21
+    @Override
22
+    public Flux<RouteDefinition> getRouteDefinitions() {
23
+        return Flux.fromIterable(routeService.getRouteDefinitions());
24
+    }
25
+
26
+    @Override
27
+    public Mono<Void> save(Mono<RouteDefinition> route) {
28
+        return route.flatMap(routeDefinition -> {
29
+            routeService.save(routeDefinition);
30
+            return Mono.empty();
31
+        });
32
+    }
33
+
34
+    @Override
35
+    public Mono<Void> delete(Mono<String> routeId) {
36
+        return routeId.flatMap(id -> {
37
+            routeService.delete(id);
38
+            return Mono.empty();
39
+        });
40
+    }
41
+}

+ 29 - 42
src/main/java/com/yaozhitech/spring5/config/Resilience4JConfiguration.java

@@ -1,50 +1,37 @@
1 1
 package com.yaozhitech.spring5.config;
2 2
 
3
-import java.time.Duration;
4
-
5
-import org.springframework.beans.factory.ObjectProvider;
6
-import org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory;
7
-import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;
8
-import org.springframework.cloud.client.circuitbreaker.Customizer;
9
-import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
10
-import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory;
11
-import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerResilience4JFilterFactory;
12
-import org.springframework.context.annotation.Bean;
13 3
 import org.springframework.context.annotation.Configuration;
14
-import org.springframework.web.reactive.DispatcherHandler;
15
-
16
-import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
17
-import io.github.resilience4j.timelimiter.TimeLimiterConfig;
18 4
 
19 5
 @Configuration
20 6
 public class Resilience4JConfiguration {
21 7
 
22
-	public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
23
-	    return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
24
-                .circuitBreakerConfig(CircuitBreakerConfig.custom().slowCallDurationThreshold(Duration.ofSeconds(4L)).build())
25
-	            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build()).build());
26
-	}
27
-
28
-	public Customizer<ReactiveResilience4JCircuitBreakerFactory> slowCustomizer() {
29
-	    return factory -> {
30
-	        factory.configure(builder -> builder
31
-	                .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
32
-	                .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()), "slow");
33
-	    };
34
-	}
35
-	
36
-	@Bean
37
-    public SpringCloudCircuitBreakerFilterFactory resilience4JCircuitBreakerFactory(
38
-            ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory,
39
-            ObjectProvider<DispatcherHandler> dispatcherHandlers) {
40
-		
41
-		// 参考自 ReactiveResilience4JCustomizerConfiguration
42
-		defaultCustomizer().customize((ReactiveResilience4JCircuitBreakerFactory) reactiveCircuitBreakerFactory);
43
-		slowCustomizer().customize((ReactiveResilience4JCircuitBreakerFactory) reactiveCircuitBreakerFactory);
44
-		
45
-//		reactiveCircuitBreakerFactory.configureDefault(id -> new Resilience4JConfigBuilder((String) id)
46
-//				.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(12)).build()).build());
47
-        return new SpringCloudCircuitBreakerResilience4JFilterFactory(reactiveCircuitBreakerFactory, 
48
-        		dispatcherHandlers);
49
-    }
8
+//	public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
9
+//		return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
10
+//				.circuitBreakerConfig(
11
+//						CircuitBreakerConfig.custom().slowCallDurationThreshold(Duration.ofSeconds(4L)).build())
12
+//				.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build()).build());
13
+//	}
14
+//
15
+//	public Customizer<ReactiveResilience4JCircuitBreakerFactory> slowCustomizer() {
16
+//		return factory -> {
17
+//			factory.configure(builder -> builder
18
+//					.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
19
+//					.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()), "slow");
20
+//		};
21
+//	}
22
+//
23
+//	@Bean
24
+//	public SpringCloudCircuitBreakerFilterFactory resilience4JCircuitBreakerFactory(
25
+//			ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory,
26
+//			ObjectProvider<DispatcherHandler> dispatcherHandlers) {
27
+//
28
+//		// 参考自 ReactiveResilience4JCustomizerConfiguration
29
+//		defaultCustomizer().customize((ReactiveResilience4JCircuitBreakerFactory) reactiveCircuitBreakerFactory);
30
+//		slowCustomizer().customize((ReactiveResilience4JCircuitBreakerFactory) reactiveCircuitBreakerFactory);
31
+//
32
+////		reactiveCircuitBreakerFactory.configureDefault(id -> new Resilience4JConfigBuilder((String) id)
33
+////				.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(12)).build()).build());
34
+//		return new SpringCloudCircuitBreakerResilience4JFilterFactory(reactiveCircuitBreakerFactory,
35
+//				dispatcherHandlers);
36
+//	}
50 37
 }

+ 12 - 12
src/main/java/com/yaozhitech/spring5/config/RouterConfig.java

@@ -28,18 +28,18 @@ public class RouterConfig {
28 28
 						.filters(f -> f.rewritePath("city_list",  // rewritePath方法会使用内建的过滤器重写路径
29 29
 								"city_list.do"))
30 30
 						.uri(httpUri))
31
-//				.route("hystrix_fallback_route", r -> r.path("/slow_query.do")
32
-//						.filters(f -> f
33
-//										.rewritePath("_query.do", "")
34
-//										.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback"))
35
-//							    )
36
-//						.uri("http://127.0.0.1:8080"))
37
-				.route("circuitbreaker_route", r -> r.path("/slow1_query.do")
38
-			            .filters(f -> f
39
-			            		.rewritePath("_query.do", "")
40
-			            		.circuitBreaker(c -> c.setName("slow").setFallbackUri("forward:/hystrixfallback"))
41
-			                )
42
-			            .uri("http://127.0.0.1:8080"))
31
+				.route("hystrix_fallback_route", r -> r.path("/slow_query.do")
32
+						.filters(f -> f
33
+										.rewritePath("_query.do", "")
34
+										.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback"))
35
+							    )
36
+						.uri("http://127.0.0.1:8080"))
37
+//				.route("circuitbreaker_route", r -> r.path("/slow1_query.do")
38
+//			            .filters(f -> f
39
+//			            		.rewritePath("_query.do", "")
40
+//			            		.circuitBreaker(c -> c.setName("slow").setFallbackUri("forward:/hystrixfallback"))
41
+//			                )
42
+//			            .uri("http://127.0.0.1:8080"))
43 43
 
44 44
 //				.route("websocket_route", r -> r.path("/echo")
45 45
 //					.uri("ws://localhost:9000"))

+ 1 - 1
src/main/java/com/yaozhitech/spring5/controller/CityWebFluxController.java

@@ -23,7 +23,7 @@ public class CityWebFluxController {
23 23
 
24 24
 	@Autowired
25 25
 	private RedisTemplate<String, Object> redisTemplate;
26
-
26
+	
27 27
 	@GetMapping(value = "/{id}")
28 28
 	public Mono<City> findCityById(@PathVariable("id") Long id) {
29 29
 		String key = "city_" + id;

+ 81 - 0
src/main/java/com/yaozhitech/spring5/service/RouteService.java

@@ -0,0 +1,81 @@
1
+package com.yaozhitech.spring5.service;
2
+
3
+import java.net.URI;
4
+import java.net.URISyntaxException;
5
+import java.util.Collection;
6
+import java.util.HashMap;
7
+import java.util.Map;
8
+import java.util.Set;
9
+import java.util.stream.Collectors;
10
+
11
+import javax.annotation.PostConstruct;
12
+
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.cloud.gateway.route.RouteDefinition;
15
+import org.springframework.data.redis.core.StringRedisTemplate;
16
+import org.springframework.stereotype.Service;
17
+import org.springframework.util.CollectionUtils;
18
+
19
+import com.alicp.jetcache.Cache;
20
+import com.alicp.jetcache.anno.CacheType;
21
+import com.alicp.jetcache.anno.CreateCache;
22
+
23
+import lombok.extern.slf4j.Slf4j;
24
+
25
+@Service
26
+@Slf4j
27
+public class RouteService {
28
+
29
+    private static final String GATEWAY_ROUTES = "gateway_routes::";
30
+
31
+    @Autowired
32
+    private StringRedisTemplate stringRedisTemplate;
33
+
34
+    @CreateCache(name = GATEWAY_ROUTES, cacheType = CacheType.REMOTE)
35
+    private Cache<String, RouteDefinition> gatewayRouteCache;
36
+
37
+    private Map<String, RouteDefinition> routeDefinitionMaps = new HashMap<>();
38
+
39
+    @PostConstruct
40
+    private void loadRouteDefinition() {
41
+        log.info("loadRouteDefinition, 开始初使化路由");
42
+        Set<String> gatewayKeys = stringRedisTemplate.keys(GATEWAY_ROUTES + "*");
43
+        if (CollectionUtils.isEmpty(gatewayKeys)) {
44
+            return;
45
+        }
46
+        log.info("预计初使化路由, gatewayKeys:{}", gatewayKeys);
47
+        // 去掉key的前缀
48
+        Set<String> gatewayKeyIds = gatewayKeys.stream().map(key -> {
49
+            return key.replace(GATEWAY_ROUTES, "");
50
+        }).collect(Collectors.toSet());
51
+        
52
+        Map<String, RouteDefinition> allRoutes = gatewayRouteCache.getAll(gatewayKeyIds);
53
+        log.info("gatewayKeys:{}", allRoutes);
54
+        // 以下代码原因是,jetcache将RouteDefinition返序列化后,uri发生变化,未初使化,导致路由异常,以下代码是重新初使化uri
55
+        allRoutes.values().forEach(routeDefinition -> {
56
+            try {
57
+                routeDefinition.setUri(new URI(routeDefinition.getUri().toASCIIString()));
58
+            } catch (URISyntaxException e) {
59
+                log.error("网关加载RouteDefinition异常:", e);
60
+            }
61
+        });
62
+        routeDefinitionMaps.putAll(allRoutes);
63
+        log.info("共初使化路由信息:{}", routeDefinitionMaps.size());
64
+    }
65
+
66
+    public Collection<RouteDefinition> getRouteDefinitions() {
67
+        return routeDefinitionMaps.values();
68
+    }
69
+
70
+    public boolean save(RouteDefinition routeDefinition) {
71
+        routeDefinitionMaps.put(routeDefinition.getId(), routeDefinition);
72
+        log.info("新增路由1条:{},目前路由共{}条", routeDefinition, routeDefinitionMaps.size());
73
+        return true;
74
+    }
75
+
76
+    public boolean delete(String routeId) {
77
+        routeDefinitionMaps.remove(routeId);
78
+        log.info("删除路由1条:{},目前路由共{}条", routeId, routeDefinitionMaps.size());
79
+        return true;
80
+    }
81
+}

+ 16 - 2
src/main/resources/application.properties

@@ -2,7 +2,7 @@
2 2
 ## Redis服务器地址
3 3
 spring.redis.host=120.55.124.69
4 4
 ## Redis服务器连接端口
5
-spring.redis.port=6279
5
+spring.redis.port=6280
6 6
 ## Redis服务器连接密码(默认为空)
7 7
 spring.redis.password=bbztx123456
8 8
 # 连接超时时间(毫秒)
@@ -17,4 +17,18 @@ spring.cloud.gateway.metrics.enabled=true
17 17
 # 开启指定端点
18 18
 management.endpoints.web.exposure.include=gateway,metrics
19 19
 
20
-        
20
+# 缓存
21
+jetcache.statIntervalMinutes: 15
22
+jetcache.areaInCacheName: false
23
+jetcache.hidePackages: com.yaozhitech.spring5
24
+#jetcache.local.default.type: caffeine
25
+#jetcache.local.default.keyConvertor: fastjson
26
+jetcache.remote.default.type: redis.lettuce
27
+jetcache.remote.default.keyConvertor: fastjson
28
+jetcache.remote.default.valueEncoder: kryo
29
+jetcache.remote.default.valueDecoder: kryo
30
+jetcache.remote.default.poolConfig.minIdle: 5
31
+jetcache.remote.default.poolConfig.maxIdle: 20
32
+jetcache.remote.default.poolConfig.maxTotal: 50
33
+jetcache.remote.default.uri: redis://bbztx123456@120.55.124.69:6280
34
+