Browse Source

动态路由

温红权 3 years ago
parent
commit
ceb959107b

BIN
.gradle/7.2/executionHistory/executionHistory.lock


BIN
.gradle/7.2/fileHashes/fileHashes.lock


BIN
.gradle/buildOutputCleanup/buildOutputCleanup.lock


+ 1 - 1
.gradle/buildOutputCleanup/cache.properties

@@ -1,2 +1,2 @@
-#Mon Dec 06 16:50:57 CST 2021
+#Thu Dec 09 11:16:18 CST 2021
 gradle.version=7.3

BIN
.gradle/checksums/checksums.lock


BIN
.gradle/checksums/md5-checksums.bin


BIN
.gradle/checksums/sha1-checksums.bin


+ 4 - 0
build.gradle

@@ -400,6 +400,10 @@ subprojects {
          implementation  group: 'com.github.xiaoymin', name: 'knife4j-spring-ui', version: "${knife4jVersion}"
          implementation  group: 'com.github.xiaoymin', name: 'knife4j-spring-boot-starter', version: "${knife4jVersion}"
          implementation  group: 'com.github.xiaoymin', name: 'knife4j-spring-boot-autoconfigure', version: "${knife4jVersion}"
+
+         //lombok
+         compileOnly 'org.projectlombok:lombok:1.18.6'
+         annotationProcessor 'org.projectlombok:lombok:1.18.6'
         
          //local jars
          implementation fileTree(dir: "${rootDir}/maxkey-lib/", include: '*.jar')

+ 110 - 0
maxkey-gateway/src/main/java/org/gateway/route/DynamicRouteServiceImpl.java

@@ -0,0 +1,110 @@
+package org.gateway.route;
+
+import com.alibaba.nacos.common.utils.CollectionUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
+import org.springframework.cloud.gateway.route.RouteDefinition;
+import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
+import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+/**
+ * 动态更新路由网关service
+ * 1)实现一个Spring提供的事件推送接口ApplicationEventPublisherAware
+ * 2)提供动态路由的基础方法,可通过获取bean操作该类的方法。该类提供新增路由、更新路由、删除路由,然后实现发布的功能。
+ */
+@Slf4j
+@Service
+public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
+    @Autowired
+    private RouteDefinitionWriter routeDefinitionWriter;
+    @Autowired
+    private RouteDefinitionLocator routeDefinitionLocator;
+
+    /**
+     * 发布事件
+     */
+    @Autowired
+    private ApplicationEventPublisher publisher;
+
+    @Override
+    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+        this.publisher = applicationEventPublisher;
+    }
+
+    /**
+     * 删除路由
+     * @param id
+     * @return
+     */
+    public String delete(String id) {
+        try {
+            log.info("gateway delete route id {}",id);
+            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
+            this.publisher.publishEvent(new RefreshRoutesEvent(this));
+            return "delete success";
+        } catch (Exception e) {
+            return "delete fail";
+        }
+    }
+
+    /**
+     * 更新路由
+     * @param definitions
+     * @return
+     */
+    public String updateList(List<RouteDefinition> definitions) {
+        log.info("gateway update route {}",definitions);
+        // 删除缓存routerDefinition
+        List<RouteDefinition> routeDefinitionsExits =  routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
+        if (!CollectionUtils.isEmpty(routeDefinitionsExits)) {
+            routeDefinitionsExits.forEach(routeDefinition -> {
+                log.info("delete routeDefinition:{}", routeDefinition);
+                delete(routeDefinition.getId());
+            });
+        }
+        definitions.forEach(definition -> {
+            updateById(definition);
+        });
+        return "success";
+    }
+
+    /**
+     * 更新路由
+     * @param definition
+     * @return
+     */
+    public String updateById(RouteDefinition definition) {
+        try {
+            log.info("gateway update route {}",definition);
+            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
+        } catch (Exception e) {
+            return "update fail,not find route  routeId: "+definition.getId();
+        }
+        try {
+            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
+            this.publisher.publishEvent(new RefreshRoutesEvent(this));
+            return "success";
+        } catch (Exception e) {
+            return "update route fail";
+        }
+    }
+
+    /**
+     * 增加路由
+     * @param definition
+     * @return
+     */
+    public String add(RouteDefinition definition) {
+        log.info("gateway add route {}",definition);
+        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
+        this.publisher.publishEvent(new RefreshRoutesEvent(this));
+        return "success";
+    }
+}

+ 99 - 0
maxkey-gateway/src/main/java/org/gateway/route/DynamicRouteServiceImplByNacos.java

@@ -0,0 +1,99 @@
+package org.gateway.route;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.route.RouteDefinition;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+
+/**
+ *
+ * 通过nacos下发动态路由配置,监听Nacos中gateway-route配置
+ *
+ */
+@Component
+@Slf4j
+@DependsOn({"gatewayConfig"}) // 依赖于gatewayConfig bean
+public class DynamicRouteServiceImplByNacos {
+
+    @Autowired
+    private DynamicRouteServiceImpl dynamicRouteService;
+
+
+    private ConfigService configService;
+
+    @PostConstruct
+    public void init() {
+        log.info("gateway route init...");
+        try{
+            configService = initConfigService();
+            if(configService == null){
+                log.warn("initConfigService fail");
+                return;
+            }
+            String configInfo = configService.getConfig(GatewayConfig.NACOS_ROUTE_DATA_ID, GatewayConfig.NACOS_ROUTE_GROUP, GatewayConfig.DEFAULT_TIMEOUT);
+            log.info("获取网关当前配置:\r\n{}",configInfo);
+            List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
+            for(RouteDefinition definition : definitionList){
+                log.info("update route : {}",definition.toString());
+                dynamicRouteService.add(definition);
+            }
+        } catch (Exception e) {
+            log.error("初始化网关路由时发生错误",e);
+        }
+        dynamicRouteByNacosListener(GatewayConfig.NACOS_ROUTE_DATA_ID,GatewayConfig.NACOS_ROUTE_GROUP);
+    }
+
+    /**
+     * 监听Nacos下发的动态路由配置
+     * @param dataId
+     * @param group
+     */
+    public void dynamicRouteByNacosListener (String dataId, String group){
+        try {
+            configService.addListener(dataId, group, new Listener()  {
+                @Override
+                public void receiveConfigInfo(String configInfo) {
+                    log.info("进行网关更新:\n\r{}",configInfo);
+                    List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
+                    log.info("update route : {}",definitionList.toString());
+                    dynamicRouteService.updateList(definitionList);
+                }
+                @Override
+                public Executor getExecutor() {
+                    log.info("getExecutor\n\r");
+                    return null;
+                }
+            });
+        } catch (NacosException e) {
+            log.error("从nacos接收动态路由配置出错!!!",e);
+        }
+    }
+
+    /**
+     * 初始化网关路由 nacos config
+     * @return
+     */
+    private ConfigService initConfigService(){
+        try{
+            Properties properties = new Properties();
+            properties.setProperty("serverAddr",GatewayConfig.NACOS_SERVER_ADDR);
+            properties.setProperty("namespace",GatewayConfig.NACOS_NAMESPACE);
+            return configService= NacosFactory.createConfigService(properties);
+        } catch (Exception e) {
+            log.error("初始化网关路由时发生错误",e);
+            return null;
+        }
+    }
+}

+ 38 - 0
maxkey-gateway/src/main/java/org/gateway/route/GatewayConfig.java

@@ -0,0 +1,38 @@
+package org.gateway.route;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class GatewayConfig {
+    public static final long DEFAULT_TIMEOUT = 30000;
+
+    public static String NACOS_SERVER_ADDR;
+
+    public static String NACOS_NAMESPACE;
+
+    public static String NACOS_ROUTE_DATA_ID;
+
+    public static String NACOS_ROUTE_GROUP;
+
+    @Value("${spring.cloud.nacos.discovery.server-addr}")
+    public void setNacosServerAddr(String nacosServerAddr){
+        NACOS_SERVER_ADDR = nacosServerAddr;
+    }
+
+    @Value("${spring.cloud.nacos.discovery.namespace}")
+    public void setNacosNamespace(String nacosNamespace){
+        NACOS_NAMESPACE = nacosNamespace;
+    }
+
+    @Value("${nacos.gateway.route.config.data-id}")
+    public void setNacosRouteDataId(String nacosRouteDataId){
+        NACOS_ROUTE_DATA_ID = nacosRouteDataId;
+    }
+
+    @Value("${nacos.gateway.route.config.group}")
+    public void setNacosRouteGroup(String nacosRouteGroup){
+        NACOS_ROUTE_GROUP = nacosRouteGroup;
+    }
+
+}

+ 0 - 146
maxkey-gateway/src/main/java/org/gateway/route/NacosDynamicRouteService.java

@@ -1,146 +0,0 @@
-/*
-package org.gateway.route;
-
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.nacos.api.NacosFactory;
-import com.alibaba.nacos.api.PropertyKeyConst;
-import com.alibaba.nacos.api.config.ConfigService;
-import com.alibaba.nacos.api.config.listener.Listener;
-import com.alibaba.nacos.api.exception.NacosException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
-import org.springframework.cloud.gateway.route.RouteDefinition;
-import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.context.ApplicationEventPublisherAware;
-import org.springframework.stereotype.Component;
-import reactor.core.publisher.Mono;
-
-import javax.annotation.PostConstruct;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-
-@Component
-public class NacosDynamicRouteService implements ApplicationEventPublisherAware
-{
-
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-
-    private String dataId = "64e29654-d4b4-4285-8bfb-f694b2c5d2ad";
-
-    private String group = "DEFAULT_GROUP";
-
-    @Value("${spring.cloud.nacos.config.server-addr}")
-    private String serverAddr;
-
-    @Value("${spring.cloud.nacos.config.namespace}")
-    private String namespace;
-
-    @Autowired
-    private RouteDefinitionWriter routeDefinitionWriter;
-
-    private ApplicationEventPublisher applicationEventPublisher;
-
-    private static final List<String> ROUTE_LIST = new ArrayList<>();
-
-    @PostConstruct
-    public void dynamicRouteByNacosListener()
-    {
-        try
-        {
-            logger.info("serverAddr:{}", serverAddr);
-            logger.info("namespace:{}", namespace);
-            logger.info("dataId:{}", dataId);
-            logger.info("group:{}", group);
-            Properties properties = new Properties();
-            properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
-            properties.put(PropertyKeyConst.NAMESPACE, namespace);
-
-            ConfigService configService = NacosFactory.createConfigService(properties);
-            configService.getConfig(dataId, group, 5000);
-
-            // 程序首次启动, 并加载初始化路由配置
-            String initConfigInfo = configService.getConfig(dataId, group, 5000);
-            addAndPublishBatchRoute(initConfigInfo);
-            publish();
-            configService.addListener(dataId, group, new Listener()
-            {
-                @Override
-                public void receiveConfigInfo(String configInfo)
-                {
-                    clearRoute();
-                    try
-                    {
-                        List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
-                        for (RouteDefinition routeDefinition : gatewayRouteDefinitions)
-                        {
-                            logger.info("routeDefinition:{}", routeDefinition);
-                            addRoute(routeDefinition);
-                        }
-                        publish();
-                    } catch (Exception e)
-                    {
-                        e.printStackTrace();
-                    }
-                }
-
-                @Override
-                public Executor getExecutor()
-                {
-                    return null;
-                }
-            });
-        } catch (NacosException e)
-        {
-            logger.error("error:{}", e);
-        }
-    }
-
-    private void clearRoute()
-    {
-        for (String id : ROUTE_LIST)
-        {
-            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
-        }
-        ROUTE_LIST.clear();
-    }
-
-    private void addAndPublishBatchRoute(String initConfigInfo)
-    {
-        List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(initConfigInfo, RouteDefinition.class);
-        for (RouteDefinition routeDefinition : gatewayRouteDefinitions)
-        {
-            logger.info("init routeDefinition:{}", routeDefinition);
-            addRoute(routeDefinition);
-        }
-    }
-
-    private void addRoute(RouteDefinition definition)
-    {
-        try
-        {
-            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
-            ROUTE_LIST.add(definition.getId());
-        } catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-    }
-
-    private void publish()
-    {
-        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
-    }
-
-    @Override
-    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
-    {
-        this.applicationEventPublisher = applicationEventPublisher;
-    }
-}
-*/

+ 18 - 15
maxkey-gateway/src/main/resources/application.yml

@@ -17,31 +17,33 @@ spring:
             - PrefixPath=/
           predicates:
             - Path=/taihu-auth/**
-        - id: taihu-demo_router
-          uri: lb://taihu-demo
-          filters:
-            - PrefixPath=/
-          predicates:
-            - Path=/taihu-demo/**
-    #      discovery:
-    #        locator:
-    #          enabled: true
-    #          lower-case-service-id: true
-    #      default-filters:
-    #       - name: Hystrix
-    #          args:
-    #            name: default
-    #            fallbackUri: 'forward:/defaultFallback'
+#        - id: taihu-demo_router
+#          uri: lb://taihu-demo
+#          filters:
+#            - PrefixPath=/
+#          predicates:
+#            - Path=/taihu-demo/**
+#          discovery:
+#            locator:
+#              enabled: true
+#              lower-case-service-id: true
+#          default-filters:
+#           - name: Hystrix
+#              args:
+#                name: default
+#                fallbackUri: 'forward:/defaultFallback'
 
     nacos:
       discovery:
         server-addr: ${NACOS_DISCOVERY_SERVER_ADDR:127.0.0.1:8848}
         enabled: ${NACOS_DISCOVERY_ENABLED:true}
+        namespace: ${NACOS_DISCOVERY_NAMESPACE:}
       config:
         #        file-extension: yaml
         #        server-addr: 127.0.0.1:8848
         username: ${NACOS_CONFIG_USERNAME:nacos}
         password: ${NACOS_CONFIG_PASSWORD:nacos}
+        namespace: ${NACOS_CONFIG_NAMESPACE:}
 
   main:
     web-application-type: reactive
@@ -60,6 +62,7 @@ spring:
         max-idle: 200
         max-active: -1
         min-idle: 0
+    database: 0
 
 hystrix:
   command:

+ 2 - 2
maxkey-gateway/src/main/resources/bootstrap.properties

@@ -1,8 +1,8 @@
 #nacos config
 spring.cloud.nacos.config.server-addr           =${NACOS_CONFIG_SERVER_ADDR:127.0.0.1:8848}
 # Nacos Console add configuration:
-# Data ID:maxkey.properties
-# Group:DEFAULT_GROUP
+nacos.gateway.route.config.data-id              =${NACOS_CONFIG_DATA_ID:gateway_config}
+nacos.gateway.route.config.group                =${NACOS_CONFIG_GROUP:DEFAULT_GROUP}
 # configuration:useLocalCache=true
 spring.application.name                         =taihu-gateway
 # Suffix for the configuration. Supports properties,yaml,yml,default is properties

+ 1 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties

@@ -127,6 +127,7 @@ spring.redis.jedis.pool.max-wait                =1000
 spring.redis.jedis.pool.max-idle                =200
 spring.redis.lettuce.pool.max-active            =-1
 spring.redis.lettuce.pool.min-idle              =0
+spring.redis.database                           =0
 
 ############################################################################
 #mail configuration                                                        #