SpringCloud Gateway 配合Nacos实现路由规则动态刷新

目的:通过nacos配置中心维护gateway的路由配置,并且在nacos上修改配置文件后无需重启就能够立即刷新路由。

1.引入maven依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 用于将yaml配置解析为javabean -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
    <version>2.12.4</version>
</dependency>

2. 编写yaml解析工具类

public class YamlUtil {
    /**
     * 将yaml字符串转成类对象
     * @param yamlStr 字符串
     * @param clazz 目标类
     * @param <T> 泛型
     * @return 目标类
     */
    public static <T> T toBean(String yamlStr, Class<T> clazz){
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        mapper.findAndRegisterModules();
        try {
            return mapper.readValue(yamlStr, clazz);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将类对象转yaml字符串
     * @param object 对象
     * @return yaml字符串
     */
    public static String toYaml(Object object){
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        mapper.findAndRegisterModules();
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER));
        StringWriter stringWriter = new StringWriter();
        try {
            mapper.writeValue(stringWriter, object);
            return stringWriter.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json转为yaml
     * json 2 yaml
     * @param jsonStr json
     * @return yaml
     * @throws JsonProcessingException Exception
     */
    public static String json2Yaml(String jsonStr) throws JsonProcessingException {
        JsonNode jsonNode = new ObjectMapper().readTree(jsonStr);
        return new YAMLMapper().writeValueAsString(jsonNode);
    }
}

3. 在nacos上创建网关路由规则相关配置文件

gateway-route.yaml

spring:
  cloud:
    gateway:
      routes:
      #物联网微服务
      - id: iotApplication
        uri: lb://iotApplication
        predicates:
          - Path=/iot/**
        filters:
          - StripPrefix=1
      #数据传输微服务
      - id: transferApplication
        uri: lb://transferApplication
        predicates:
          - Path=/transfer/**
        filters:
          - StripPrefix=1
      #测试跳转百度
      - id: Baidu
        uri: http://www.baidu.com
        predicates:
          - Path=/baidu/**
        filters:
          - StripPrefix=1

4. 编写yaml映射类

主要用户将上面的配置文件转为java Bean对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GatewayRouteConfigProperties {

    private Spring spring;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Spring{
        private Cloud cloud;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Cloud{
        private Gateway gateway;
    }
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Gateway{
        private List<RouteDefinition> routes;
    }

    public List<RouteDefinition> getRouteDefinition(){
        return spring.cloud.gateway.routes;
    };
}

5. 新增配置类,监听nacos配置文件修改网关配置

@Slf4j
@ConditionalOnBean(NacosConfigProperties.class)
@Configuration
public class DynamicRouteConfiguration implements ApplicationEventPublisherAware  {

    @Autowired
    private NacosConfigProperties nacosConfigProperties;

    @Value("${spring.cloud.gateway.dynamic.data-id:gateway-route}")
    private String dataId;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher applicationEventPublisher;

    //用于记录加载的配置文件
    private static final List<String> ROUTE_LIST = Collections.synchronizedList(new ArrayList<>());

    @PostConstruct
    public void dynamicRouteByNacosListener() {
        try {

            ConfigService configService = NacosFactory.createConfigService(nacosConfigProperties.assembleConfigServiceProperties());
            // 程序首次启动, 并加载初始化路由配置
            String initConfigInfo = configService.getConfig(dataId, nacosConfigProperties.getGroup(), 5000);

            this.addRouteConfig(initConfigInfo);

            //添加监听器监听nacos配置文件内的路由变化
            configService.addListener(dataId, nacosConfigProperties.getGroup(), new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    refreshRouteConfig(configInfo);
                }
                @Override
                public Executor getExecutor() {return null;}
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }


    private void publish() {
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * 刷新路由配置
     * @param configInfo 配置文件字符串, 必须为json array格式
     */
    private void refreshRouteConfig(String configInfo) {
        clearRoute();
        addRouteConfig(configInfo);
    }

    private void addRouteConfig(String configInfo) {
        try {
            //将yaml转为java对象
            GatewayRouteConfigProperties gatewayRouteConfig = YamlUtil.toBean(configInfo, GatewayRouteConfigProperties.class);

            if( gatewayRouteConfig!=null && CollUtil.isNotEmpty( gatewayRouteConfig.getRouteDefinition() ) ){
                gatewayRouteConfig.getRouteDefinition().parallelStream().forEach(this::addRoute);
            }

            publish();
            log.info("动态配置路由加载完成 {}", JSONUtil.toJsonStr(gatewayRouteConfig));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清除路由信息
     */
    private void clearRoute() {
        ROUTE_LIST.stream().forEach( id ->{
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        });
        ROUTE_LIST.clear();
    }

    /**
     * 添加路由
     */
    private void addRoute(RouteDefinition definition) {
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            ROUTE_LIST.add(definition.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

大功告成,试试动态修改nacos的配置文件,网关能够立即刷新路由规则,不用每次修改规则都要重启了。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway 是一个基于 Spring Framework 5、Project Reactor 和 Spring Boot 2 的反应式 API 网关。它旨在为微服务架构提供一种简单而有效的方式来路由请求,并提供一些常见的网关功能,如过滤器、负载均衡、熔断等。 而 Nacos 是一个动态服务发现、配置管理和服务管理平台,它提供了一种简单易用的方式来管理和配置微服务。可以通过 Nacos 提供的配置中心功能,实现动态配置 Spring Cloud Gateway路由规则。 下面是使用 Nacos 配置文件的动态路由的步骤: 1. 添加依赖:在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> ``` 2. 配置 Nacos:在 application.properties 或 application.yml 文件中配置 Nacos 的地址和其他相关配置: ```yaml spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 ``` 3. 创建动态路由配置文件:在 Nacos 的配置中心创建一个配置文件,例如 `gateway-route.yaml`,内容如下: ```yaml spring: cloud: gateway: routes: - id: demo_route uri: http://httpbin.org:80 predicates: - Path=/get ``` 4. 启用动态路由配置:在 Spring Cloud Gateway 的配置类中添加 `@RefreshScope` 注解,以支持动态刷新配置: ```java @Configuration @RefreshScope public class GatewayConfig { // 配置相关的 Bean } ``` 5. 启动应用程序:启动 Spring Boot 应用程序,并确保 Nacos 服务正常运行。 6. 动态刷新路由配置:在 Nacos 的配置中心修改 `gateway-route.yaml` 文件中的路由信息,并发布配置。 7. 查看动态路由:访问 Spring Cloud Gateway 的管理端点 `/actuator/gateway/routes`,可以看到动态路由已经生效。 通过以上步骤,就可以实现基于 Nacos 配置文件的动态路由。需要注意的是,Nacos 配置中心支持监听配置变更,当配置文件发生变化时,Spring Cloud Gateway 会自动刷新路由配置,无需重启应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值