简介

gateway的路由信息在项目启动时会被初始化好,如果我们需要增加或删除路由,就需要重启网关项目。本文介绍下gateway网关整合Nacos来实现动态路由,原理就不介绍了,直接上代码。

如何开始

增加依赖包:

     <!--spring cloud nacos config -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <!-- spring cloud nacos discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

yml配置:

spring:
  main:
    allow-bean-definition-overriding: true
  cloud:
    # nacos-配置
    nacos:
      config:
        # 是否开启配置中心,默认true
        enabled: true
        server-addr: 111.231.111.150:8848
        file-extension: yaml
        encode: UTF-8
        # 命名空间的id
        namespace: d10ded89-2ce5-4cf9-ad2c-4e36f9b2be7e
        group: CLOUD_PLUS
        router-data-id: gateway-router.json
      discovery:
        # 是否开启注册中心,默认true
        enabled: true
        group: ${spring.cloud.nacos.config.group}
        # 默认应用名
        service: ${spring.application.name}
        server-addr: ${spring.cloud.nacos.config.server-addr}
        namespace: ${spring.cloud.nacos.config.namespace}
    gateway:
      enabled: true
      discovery:
        locator:
          enable: true
          lower-case-service-id: true
          filters:
            - StripPrefix=1

      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_UNIQUE
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedHeaders: '*'
            allowedMethods: '*'
            allowedOrigins: '*'

management:
  endpoints:
    health:
      show-details: always
    web:
      exposure:
        include: '*'

配置类信息

/**
 * 动态路由配置
 *
 * @author gourd.hu
 */
@Configuration
public class DynamicRouteConfig {
    @Autowired
    private ApplicationEventPublisher publisher;

    @Value("${spring.cloud.nacos.config.router-data-id:gateway-router.json}")
    private String routerDataId;

    /**
     * Nacos实现方式
     */
    @Configuration
    public class NacosDynRoute {
        @Autowired
        private NacosConfigProperties nacosConfigProperties;

        @Bean
        public NacosRouteDefinitionRepository nacosRouteDefinitionRepository() {
            return new NacosRouteDefinitionRepository(routerDataId,publisher, nacosConfigProperties);
        }
    }
}
/**
 * nacos路由数据源
 *
 * @author gourd-hu
 */
@Slf4j
public class NacosRouteDefinitionRepository implements RouteDefinitionRepository {

    private String routerDataId;

    private ApplicationEventPublisher publisher;

    private NacosConfigProperties nacosConfigProperties;

    public NacosRouteDefinitionRepository(String routerDataId, ApplicationEventPublisher publisher, NacosConfigProperties nacosConfigProperties) {
        this.routerDataId = routerDataId;
        this.publisher = publisher;
        this.nacosConfigProperties = nacosConfigProperties;
        addListener();
    }

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        try {
            String content = nacosConfigProperties.configServiceInstance().getConfig(routerDataId, nacosConfigProperties.getGroup(), 5000);
            List<RouteDefinition> routeDefinitions = getListByStr(content);
            return Flux.fromIterable(routeDefinitions);
        } catch (NacosException e) {
            log.error("getRouteDefinitions by nacos error", e);
        }
        return Flux.fromIterable(Collections.EMPTY_LIST);
    }

    /**
     * 添加Nacos监听
     */
    private void addListener() {
        try {
            nacosConfigProperties.configServiceInstance().addListener(routerDataId, nacosConfigProperties.getGroup(), new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    publisher.publishEvent(new RefreshRoutesEvent(this));
                }
            });
        } catch (NacosException e) {
            log.error("nacos-addListener-error", e);
        }
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return null;
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return null;
    }

    /**
     * 解析路由
     * @param content
     * @return
     */
    private List<RouteDefinition> getListByStr(String content) {
        if (StringUtils.isNotEmpty(content)) {
            return JSONObject.parseArray(content, RouteDefinition.class);
        }
        return new ArrayList<>(0);
    }
}

Naocs中路由配置

在这里插入图片描述
样例:

[{
    "filters": [{
         "args": {
            "parts": "1"
        },
        "name": "StripPrefix"
    }],
    "id": "admin-service",
    "order": 0,
    "predicates": [{
        "args": {
            "pattern": "/admin/**"
        },
        "name": "Path"
    }],
    "uri": "lb://admin"
},
{
    "filters": [{
         "args": {
            "parts": "1"
        },
        "name": "StripPrefix"
    }],
    "id": "sub-service",
    "order": 0,
    "predicates": [{
        "args": {
            "pattern": "/sub/**"
        },
        "name": "Path"
    }],
    "uri": "lb://sub"
}]

启动项目查看路由信息

启动完项目后,通过浏览器访问:ip+port+/actuator/gateway/routes 查看路由信息。
在这里插入图片描述在Nacos中修改路由配置,再次访问发现路由是修改后的,这里就不截图了,到此动态路由就整合好了。

=================================================
代码已上传至我的开源项目,有兴趣的小伙伴可以下载:
https://blog.csdn.net/HXNLYW/article/details/104635673

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐