当前位置: 首页 > article >正文

nacos-gateway动态路由

在Nacos官网中给出了手动监听Nacos配置变更的SDK:

Nacos Java SDK


所需依赖

<!--统一配置管理-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--加载bootstrap-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

nacos提供了监视配置文件的功能,当配置文件发生更改的能够实时推送到服务器,这个时候我们就能够获取最新的配置去做操作,比如与gateway进行配合实现动态路由,这里需要了解几个类和接口以及方法:

1. RouteDefinitionWriter :gateway提供的接口,用于动态的添加路由

2. NacosConfigManager :nacos提供的接口,用于与配置中心做交互

RouteDefinitionWriter:

RouteDefinitionWriter 是 Spring Cloud Gateway 提供的一个接口,用于动态地添加、更新和删除路由定义。它允许你在应用程序运行时修改网关的路由配置,而无需重启服务。

主要功能:

添加路由定义:

使用 save(Mono<RouteDefinition> route) 方法可以添加一个新的路由定义。

如果路由定义已经存在,则会更新该路由定义。

删除路由定义:

使用 delete(Mono<String> id) 方法可以根据路由ID删除一个路由定义。

更新路由定义:

通过 save(Mono<RouteDefinition> route) 方法可以更新现有的路由定义。

主要方法:

save(Mono<RouteDefinition> route): 保存一个新的路由定义或更新现有的路由定义。
delete(Mono<String> id): 根据路由ID删除一个路由定义

NacosConfigManager:

NacosConfigManager 是 Spring Cloud Alibaba Nacos 提供的一个配置管理器,用于与 Nacos 配置中心进行交互。它允许你在应用程序中方便地获取、监听和更新 Nacos 中的配置信息。

主要功能

获取配置:从 Nacos 配置中心获取指定 Data ID 和 Group 的配置信息。

注册监听器:为指定的配置项注册监听器,以便在配置发生变化时能够及时接收到通知并作出相应处理。

主要方法

getConfigService(): 获取 ConfigService 实例,用于执行具体的配置操作。

getConfig(String dataId, String group, long timeoutMs): 根据 Data ID 和 Group 获取配置信息,并设置超时时间。

addListener(String dataId, String group, Listener listener): 为指定的配置项添加监听器。

removeListener(String dataId, String group, Listener listener): 移除指定的监听器。

实操

控制台示例


模板

根据上面的信息,下面就是代码案例,实际使用只需要修改id和group

package com.hmall.gateway.route;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.hmall.common.utils.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * 动态路由加载器,用于从Nacos配置中心动态加载和更新路由配置
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {

    // 路由定义写入器,用于更新路由配置
    private final RouteDefinitionWriter writer;
    // Nacos配置管理器,用于从Nacos获取配置信息
    private final NacosConfigManager nacosConfigManager;

    // 路由配置文件的id和分组
    private final String dataId = "gateway-routes.json";
    private final String group = "DEFAULT_GROUP";
    // 保存更新过的路由id
    private final Set<String> routeIds = new HashSet<>();

    /**
     * 初始化路由配置监听器,启动时从Nacos拉取最新的路由配置并监听后续的配置变更
     */
    @PostConstruct // 在容器启动时执行
    public void initRouteConfigListener() throws NacosException {
        // 1.注册监听器并首次拉取配置
        String configInfo = nacosConfigManager.getConfigService() // 获取配置服务
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {// 监听器

                    @Override
                    public Executor getExecutor() { // 线程池
                        return null;
                    }

                    /**
                     * 配置信息变更时回调
                     * @param configInfo 返回的配置信息
                     */
                    @Override
                    public void receiveConfigInfo(String configInfo) { // 配置信息变更时回调
                        updateConfigInfo(configInfo);
                    }
                });
        // 2.首次启动时,更新一次配置
        updateConfigInfo(configInfo);
    }

    /**
     * 更新路由配置信息
     *
     * @param configInfo 路由配置信息,JSON格式
     */
    private void updateConfigInfo(String configInfo) {
        log.debug("监听到路由配置变更,{}", configInfo);
        // 1.反序列化
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
        // 2.更新前先清空旧路由
        // 2.1.清除旧路由
        for (String routeId : routeIds) {
            writer.delete(Mono.just(routeId)).subscribe();
        }
        routeIds.clear();
        // 2.2.判断是否有新的路由要更新
        if (CollUtils.isEmpty(routeDefinitions)) {
            // 无新路由配置,直接结束
            return;
        }
        // 3.更新路由
        routeDefinitions.forEach(routeDefinition -> {
            // 3.1.更新路由
            writer.save(Mono.just(routeDefinition)).subscribe(); //subscribe()用于异步执行,不阻塞当前线程
            // 3.2.记录路由id,方便将来删除
            routeIds.add(routeDefinition.getId());
        });
    }
}

配置中心模板

{
  // 路由的唯一标识符
  "id": "item",
  
  // 路由的匹配规则
  "predicates": [
    {
      // 使用 Path 匹配规则
      "name": "Path",
      
      // 匹配的路径模式
      "args": {
        // 匹配 /items/** 路径
        "pattern1": "/items/**",
        
        // 匹配 /search/** 路径
        "pattern2": "/search/**"
      }
    }
  ],
  
  // 路由的过滤器(当前没有过滤器)
  "filters": [],
  
  // 路由的目标服务地址,使用负载均衡
  "uri": "lb://item-service"
}

上面这一段就等同于是之前的这一段

spring:
  cloud:
    gateway:
      routes:
        - id: item
          uri: lb://item-service
          predicates:
            - Path=/items/**,/search/**

bootstrap.yaml

spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos注册中心地址
      config:
        file-extension: yaml # 配置文件后缀
        shared-configs: # 共享配置
          - data-id: shared-log.yaml # 日志配置文件


http://www.kler.cn/a/459240.html

相关文章:

  • GeoTrust True BusinessID Wildcard
  • 算命占卜网php源码/设计书/2025八字运势怎么通过php测算
  • MySQL数据库——常见慢查询优化方式
  • Android性能优化概述
  • 如何在梯度计算中处理bf16精度损失:混合精度训练中的误差分析
  • Microsoft word@【标题样式】应用不生效(主要表现为在导航窗格不显示)
  • Java工具类Arrays
  • GPIO相关寄存器,点灯
  • 一次 MySQL IF 函数的误用导致的生产小事故
  • linux上虚拟机显示网络不可用的解决方法
  • 建立一个Macos载入image的实例含界面
  • docker 部署mysql8
  • MySQL如何执行.sql 文件:详细教学指南
  • 今日总结 2024-12-30
  • LeetCode热题100-两数之和【JavaScript讲解】
  • 信息系统常见的系统架构
  • 老鑫网络安全培训课程收费多少钱
  • 知识图谱+大模型:打造全新智慧城市底层架构
  • 数据链路层知识要点
  • VSCode 插件开发实战(十): 环境变量Env设置与管理
  • svn分支相关操作(小乌龟操作版)
  • 添加购物车业务代码
  • 概率论与随机过程--作业2
  • vscode中调用deepseek实现AI辅助编程
  • Mcnemar‘s exact test
  • 【面试系列】深入浅出 Spring Boot