nacos — 动态路由

Nacos 是一个阿里巴巴开源的服务注册中心,广泛用于微服务架构中。它除了支持服务注册和配置管理外,还可以配合网关实现动态路由。动态路由能够根据配置的实时更新动态调整路由规则,避免应用重启,实现路由的灵活管理。

网关的路由配置全部是在项目启动时由org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator在项目启动的时候加载,并且一经加载就会缓存到内存中的路由表内(一个Map),不会改变。也不会监听路由变更,所以,我们无法利用配置热更新来实现路由更新。

因此,我们必须监听Nacos的配置变更,然后手动把最新的路由更新到路由表中。

1. 监听Nacos配置变更

在Nacos官网中给出了手动监听Nacos配置变更的SDK:https://nacos.io/zh-cn/docs/sdk.html

通过 NacosConfigManager 注册监听器。

2. 更新路由

通过 RouteDefinitionWriter 更新路由。

3. 实现动态路由

3.1 引入依赖

<!--统一配置管理-->
<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>

3.2 配置文件

在网关gatewayresources目录创建bootstrap.yaml文件,配置nacos地址,内容如下:

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: 192.168.1.101

3.3 监听器

package com.cyt.gateway.route;

@Slf4j // 使用 Lombok 自动生成一个 log 对象,用于记录日志
@Component // 将该类标记为 Spring 组件,使其被 Spring 容器管理
@RequiredArgsConstructor // Lombok 注解,自动生成包含所有 `final` 字段的构造函数,方便依赖注入
public class DynamicRouteLoader {

    // 用于添加或删除网关的路由定义,通过 Spring 注入
    private final RouteDefinitionWriter writer;
    
    // 用于访问 Nacos 配置服务的管理器,通过 Spring 注入
    private final NacosConfigManager nacosConfigManager;

    // Nacos 配置的 dataId,用于标识存储网关路由配置的文件名
    private final String dataId = "gateway-routes.json";
    
    // Nacos 配置的 group,标识配置所属的分组
    private final String group = "DEFAULT_GROUP";
    
    // 用于记录当前加载的路由 ID 集合,便于清除旧的路由配置
    private final Set<String> routeIds = new HashSet<>();

    /**
     * 初始化方法,在类实例化后自动调用,用于注册 Nacos 配置监听器和首次加载路由配置
     * 
     * @throws NacosException 如果 Nacos 配置服务出现异常
     */
    @PostConstruct // 指示该方法在依赖注入完成后自动执行,用于初始化操作
    public void initRouteConfigListener() throws NacosException {
        // 1. 注册监听器并首次拉取配置
        String configInfo = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {
                    @Override
                    public Executor getExecutor() {
                        // 使用默认线程池执行回调
                        return null;
                    }

                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        // 当检测到路由配置发生变化时,调用 updateConfigInfo 更新路由
                        updateConfigInfo(configInfo);
                    }
                });
        // 2. 初始化时,获取当前配置并更新一次路由
        updateConfigInfo(configInfo);
    }

    /**
     * 更新路由配置的方法
     * 
     * @param configInfo 从 Nacos 获取的路由配置信息(JSON 格式字符串)
     */
    private void updateConfigInfo(String configInfo) {
        log.debug("监听到路由配置变更,{}", configInfo);
        
        // 1. 将 JSON 格式的路由配置字符串解析为 RouteDefinition 对象列表
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
        
        // 2. 清除旧路由配置,避免重复加载
        // 2.1 遍历 routeIds 集合,删除之前加载的路由定义
        for (String routeId : routeIds) {
            writer.delete(Mono.just(routeId)).subscribe(); // 异步删除路由
        }
        // 清空 routeIds 集合,以便保存新的路由 ID
        routeIds.clear();
        
        // 2.2 判断是否有新的路由配置
        if (CollUtils.isEmpty(routeDefinitions)) {
            // 如果没有新路由配置,则直接返回,不进行后续操作
            return;
        }
        
        // 3. 将新的路由定义添加到网关
        routeDefinitions.forEach(routeDefinition -> {
            // 3.1 调用 writer.save() 将新的路由定义保存到网关
            writer.save(Mono.just(routeDefinition)).subscribe(); // 异步保存路由
            // 3.2 记录新加载的路由 ID,便于后续清除旧的路由配置
            routeIds.add(routeDefinition.getId());
        });
    }
}

代码详细解释

  1. @Slf4j:这是 Lombok 的注解,用于自动生成一个 log 对象,可以直接在类中使用 log.debug()log.info() 等方法记录日志,方便跟踪和调试程序的执行过程。

  2. @Component:这是 Spring 的注解,表示这个类是一个 Spring 组件。Spring 会扫描到该类并将其实例化并放入容器中,以便在其他地方进行注入。

  3. @RequiredArgsConstructor:这是 Lombok 的注解,用于自动生成带有 final 字段的构造函数。在本例中,它会为 RouteDefinitionWriterNacosConfigManager 两个字段生成构造方法,使它们可以通过构造函数注入。这种方式可以避免手动写构造函数,减少代码量。

  4. RouteDefinitionWriter:这是 Spring Cloud Gateway 提供的接口,用于动态添加和删除网关的路由定义。通过该接口,可以在不重启网关的情况下更新路由配置。

  5. NacosConfigManager:这是 Alibaba 提供的 Nacos 配置管理器,用于从 Nacos 配置中心获取配置信息和监听配置变更。Nacos 是一个分布式配置中心和服务注册中心,提供配置管理和服务发现功能。

  6. dataIdgroup 字段:这些字段是用来从 Nacos 配置中心读取配置的标识:

    • dataId:指定了配置文件的名称,这里是 "gateway-routes.json",该文件存储了网关的路由配置信息。
    • group:指定了配置文件所属的组名,这里是 "DEFAULT_GROUP"。在 Nacos 中,可以将配置文件按组进行分类管理。
  7. routeIds:用于存储当前已加载的路由 ID 集合,便于在路由更新时清除旧的路由定义,防止新旧路由冲突。

  8. @PostConstruct:这是一个 Java 的注解,表示在依赖注入完成后会自动调用该方法。在本例中,initRouteConfigListener 方法会在 Spring 完成依赖注入后执行,注册一个 Nacos 监听器并首次加载路由配置。

initRouteConfigListener 方法

该方法在初始化时执行,用于向 Nacos 注册监听器,并首次拉取路由配置:

  • 注册监听器:调用 getConfigAndSignListener 方法向 Nacos 注册监听器,指定 dataIdgroup 来监听相应的路由配置。当配置发生变更时,Nacos 会调用 receiveConfigInfo 方法。
  • 首次拉取配置:注册监听器后,同步获取当前配置,接着调用 updateConfigInfo 方法更新路由配置。

updateConfigInfo 方法

该方法接收从 Nacos 获取的配置信息,并更新网关的路由配置:

  1. 反序列化配置:使用 JSONUtil.toList 将 JSON 格式的配置内容转换为 RouteDefinition 对象列表。每个 RouteDefinition 对象代表一个路由定义。

  2. 清除旧路由

    • 遍历 routeIds 集合,删除之前的路由定义,防止新旧路由冲突。
    • 清空 routeIds 集合,以便保存新的路由 ID。
  3. 检查新配置

    • 使用工具类 CollUtils.isEmpty 判断 routeDefinitions 列表是否为空,如果为空则直接结束方法。
  4. 保存新路由

    • 遍历 routeDefinitions 列表,逐个将新的 RouteDefinition 对象保存到网关中。
    • 将每个路由的 ID 添加到 routeIds 集合,便于记录当前加载的路由配置。

3.4 添加路由文件

根据监听器中,所配置的group和dataId,在Nacos控制台添加路由,路由文件名为gateway-routes.json,类型为json

配置内容示例:

[
    {
        // 路由的唯一标识符
        "id": "item",
        
        // 路由的谓词(predicates)配置,用于匹配请求路径
        "predicates": [
            {
                // 使用路径匹配谓词,匹配路径规则
                "name": "Path",
                
                // 路径参数,定义需要匹配的 URL 路径
                "args": {
                    "_genkey_0": "/items/**",     // 匹配路径为 /items/ 下的所有请求
                    "_genkey_1": "/search/**"     // 以及 /search/ 下的所有请求
                }
            }
        ],
        
        // 过滤器(filters)配置,用于对请求或响应进行处理,当前无过滤器
        "filters": [],
        
        // 路由的目标 URI,这里指定了一个逻辑负载均衡的服务名,将请求转发到 item-service
        "uri": "lb://item-service"
    },
    {
        "id": "cart",
        "predicates": [
            {
                "name": "Path",
                "args": {
                    "_genkey_0": "/carts/**"     // 匹配 /carts/ 下的所有请求
                }
            }
        ],
        "filters": [],
        "uri": "lb://cart-service"            // 将请求转发到 cart-service
    }
]
智能网联汽车的安全员高级考试涉及多个方面的专业知识,包括但不限于自动驾驶技术原理、车辆传感器融合、网络安全防护以及法律法规等内容。以下是针对该主题的一些核心知识解析: ### 关于智能网联车安全员高级考试的核心内容 #### 1. 自动驾驶分级标准 国际自动机工程师学会(SAE International)定义了六个级别的自动驾驶等级,从L0到L5[^1]。其中,L3及以上级别需要安全员具备更高的应急处理能力。 #### 2. 车辆感知系统的组成与功能 智能网联车通常配备多种传感器,如激光雷达、毫米波雷达、摄像头和超声波传感器等。这些设备协同工作以实现环境感知、障碍物检测等功能[^2]。 #### 3. 数据通信与网络安全 智能网联车依赖V2X(Vehicle-to-Everything)技术进行数据交换,在此过程中需防范潜在的网络攻击风险,例如中间人攻击或恶意软件入侵[^3]。 #### 4. 法律法规要求 不同国家和地区对于无人驾驶测试及运营有着严格的规定,考生应熟悉当地交通法典中有关自动化驾驶部分的具体条款[^4]。 ```python # 示例代码:模拟简单决策逻辑 def decide_action(sensor_data): if sensor_data['obstacle'] and not sensor_data['emergency']: return 'slow_down' elif sensor_data['pedestrian_crossing']: return 'stop_and_yield' else: return 'continue_driving' example_input = {'obstacle': True, 'emergency': False, 'pedestrian_crossing': False} action = decide_action(example_input) print(f"Action to take: {action}") ``` 需要注意的是,“同学”作为特定平台上的学习资源名称,并不提供官方认证的标准答案集;建议通过正规渠道获取教材并参加培训课程来准备此类资格认证考试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyt涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值