spring-gateway 基于 nacos 配置文件的动态路由

简介: spring-gateway 基于 nacos 配置文件的动态路由

动态路由的实现方式多种多样,研究一下基于 nacos 配置文件形式的动态路由。


1. 创建项目,并pom.xml文件引入如下依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.olive</groupId>
 <artifactId>olive-gateway</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.1</version>
 </parent>
 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>2021.0.3</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
   <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2021.1</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>
 <dependencies>
  <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</groupId>
      <artifactId>fastjson</artifactId>
      <version>2.0.9</version>
  </dependency>
 </dependencies>
</project>

2. 增加一个配置类

主要配置 nacos 的 dataId 与 group

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "route.nacos")
public class GatewayConfig {
    private String dataId;
    private String group;
    private int timeout;
    //省略 getter  setter   
}


3.定义监听路由变化类

InFileRouteDefinitionRepository 类主要是简单 nacos 中的配置文件routes.json 的变化;只要监听到 routes.json 就进行路由更新。

import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.PostConstruct;
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 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 com.alibaba.nacos.common.utils.CollectionUtils;
import com.olive.config.GatewayConfig;
import com.olive.route.model.GatewayRouteDO;
import reactor.core.publisher.Mono;
@Component
public class InFileRouteDefinitionRepository implements ApplicationEventPublisherAware{
    @Value("${spring.cloud.nacos.discovery.server-addr}")
    private String nacosServer;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher publisher;
    @Autowired
    private GatewayConfig gatewayConfig;
   @PostConstruct
   private void init() {
       dynamicRouteByListener(gatewayConfig.getDataId(), gatewayConfig.getGroup(), 
           nacosServer, gatewayConfig.getTimeout());
   }
    /**
     * 监听Nacos Server下发的动态路由配置
     */
    public void dynamicRouteByListener(String dataId, String group, String nacosServer, int timeout) {
        try {
            ConfigService configService = NacosFactory.createConfigService(nacosServer);
            String content = configService.getConfig(dataId, group, timeout);
            configService.addListener(dataId, group, new Listener() {
             @Override
                public void receiveConfigInfo(String configInfo) {
                    updateConfig(configInfo);
                }
                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
            updateConfig(content);
        } catch (NacosException e) {
         e.printStackTrace();
        }
    }
    private void updateConfig(String configInfo) {
        try {
            GatewayRouteDO gatewayRouteDO = JSON.parseObject(configInfo, GatewayRouteDO.class);
            List<RouteDefinition> routeList = gatewayRouteDO.getRoutes();
            if (CollectionUtils.isNotEmpty(routeList)) {
                for (RouteDefinition routeDefinition : routeList) {
                    this.update(routeDefinition);
                }
            }
        } catch (Exception e) {
         e.printStackTrace();
        }
    }
    /**
     * 增加路由
     */
    public String add(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }
    /**
     * 更新路由
     */
    public String update(RouteDefinition definition) {
        try {
            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) {
         e.printStackTrace();
            return "update route fail";
        }
    }
    /**
     * 删除路由
     */
    public String delete(String id) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(id));
            return "delete success";
        } catch (Exception e) {
            e.printStackTrace();
            return "delete route fail";
        }
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

4. 增加 application.yml 配置文件

server:
  port: 8089
spring:
  application:
    name: olive-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.255.10:8848
route:
  nacos:
    dataId: routes.json
    group: DEFAULT_GROUP
    timeout: 1000

需要在配置中心 nacos 增加 routes.json 配置文件;这个 json 文件的格式一定要符合 spring-gateway 的 route 格式;否则无法转换。routes.json 内容如下:

{
  "routes": [
    {
      "filters": [],
      "id": "pay_route",
      "order": 0,
      "predicates": [
        {
          "args": {
            "pattern": "/pay/**"
          },
          "name": "Path"
        }
      ],
      "uri": "lb://pay-service"
    },
    {
      "filters": [
        {
          "name": "RewritePath",
          "args": {
            "regexp": "/user/(?<remaining>.*)",
            "replacement": "/${remaining}"
          }
        }
      ],
      "id": "user_route",
      "order": 0,
      "predicates": [
        {
          "args": {
            "pattern": "/user/**"
          },
          "name": "Path"
        }
      ],
      "uri": "lb://user-center-service"
    }
  ]
}

5. 创建springboot 引导类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class GwApplication {
 public static void main(String[] args) {
   SpringApplication.run(GwApplication.class, args);
 }
}

测试验证只要通过在配置中心 nacos;修改 routes.json 配置文件即可。

相关文章
|
5月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
11月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2707 1
|
6月前
|
API
使用Gateway with Inference Extension路由外部MaaS服务
本文介绍如何通过Gateway with Inference Extension对接百炼服务,实现请求路由时自动添加API Key并重写路径,包含操作步骤及验证方法。
|
XML Java 数据格式
Spring从入门到入土(xml配置文件的基础使用方式)
本文详细介绍了Spring框架中XML配置文件的使用方法,包括读取配置文件、创建带参数的构造对象、使用工厂方法和静态方法创建对象、对象生命周期管理以及单例和多例模式的测试。
779 7
Spring从入门到入土(xml配置文件的基础使用方式)
|
11月前
|
存储 人工智能 Kubernetes
ACK Gateway with AI Extension:面向Kubernetes大模型推理的智能路由实践
本文介绍了如何利用阿里云容器服务ACK推出的ACK Gateway with AI Extension组件,在Kubernetes环境中为大语言模型(LLM)推理服务提供智能路由和负载均衡能力。文章以部署和优化QwQ-32B模型为例,详细展示了从环境准备到性能测试的完整实践过程。
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
11月前
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——指定项目配置文件
在实际项目中,开发环境和生产环境的配置往往不同。为简化配置切换,可通过创建 `application-dev.yml` 和 `application-pro.yml` 分别管理开发与生产环境配置,如设置不同端口(8001/8002)。在 `application.yml` 中使用 `spring.profiles.active` 指定加载的配置文件,实现环境快速切换。本节还介绍了通过配置类读取参数的方法,适用于微服务场景,提升代码可维护性。课程源码可从 [Gitee](https://gitee.com/eson15/springboot_study) 下载。
481 0
|
Java 测试技术 应用服务中间件
Spring Boot 配置文件总结
Spring Boot 提供全局配置文件 `application.properties` 和 `application.yml`,用于修改自动配置的默认值。前者使用键值对配置,后者使用缩进和冒号。不同环境(开发、测试、生产)可切换配置文件,通过 `spring.profiles.active` 指定。例如,开发环境端口为4790,测试环境为4791,生产环境为4792。配置示例展示了属性、List、Map定义及引用方法。
418 14
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
1326 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件

热门文章

最新文章