Spring cloud gateway nacos实现动态路由

Spring cloud gateway的三个核心概念

route 路由

可以理解为一条转发规则,包含:

  • id
  • 目标url
  • 断言(predicate)
  • 过滤器(filter)
    若断言为true,则请求将经由 filter 被路由到目标 url。

predicate 断言

可以理解为一个条件判断,对当前的http请求进行指定规则的匹配,当匹配上规则时,断言才为true,此时请求会被路由到目标地址,服务或者过滤器

filter 过滤器

对请求进行处理的逻辑部分。当请求的断言为true 时,会被路由到设置好的过滤器, 以对请求进行处理。例如,可以为请求添加一个请求头,或添加一个请求参数,或对请求URI 进行修改等。

Nacos作为路由规则的配置中心

nacos的配置和运行如下

  • MySQL配置运行
  • 运行MySQL

    docker run -p 3306:3306 --name mysql \
    -v /Users/wangbin/dockerall/mysql/log:/var/log/mysql \
    -v /Users/wangbin/dockerall/mysql/data:/var/lib/mysql \
    -v /Users/wangbin/dockerall/mysql/conf:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    -d mysql:5.7
    
    docker exec -it mysql bash
    
    mysql -proot
    
    create database nacos_config;
    
    use nacos_config;
    
  • 执行SQL
    SQL内容
  • 新建/xxxxx/nacos_docker/init.d/目录并生成custom.properties文件。文件内容如下

    management.endpoints.web.exposure.include=*
    server.contextPath=/nacos
    server.servlet.contextPath=/nacos
    server.port=8848
    spring.datasource.platform=mysql
    db.num=1
    db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
    db.user=root
    db.password=root
    nacos.cmdb.dumpTaskInterval=3600
    nacos.cmdb.eventTaskInterval=10
    nacos.cmdb.labelTaskInterval=300
    nacos.cmdb.loadDataAtStart=false
    management.metrics.export.elastic.enabled=false
    management.metrics.export.influx.enabled=false
    server.tomcat.accesslog.enabled=true
    server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i
    nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
    nacos.naming.distro.taskDispatchThreadCount=1
    nacos.naming.distro.taskDispatchPeriod=200
    nacos.naming.distro.batchSyncKeyCount=1000
    nacos.naming.distro.initDataRatio=0.9
    nacos.naming.distro.syncRetryDelay=5000
    nacos.naming.data.warmup=true
    nacos.naming.expireInstance=true
  • 新建logs目录
  • 运行Nacos

    docker run
    --name nacos -d
    -p 8848:8848
    --privileged=true
    --restart=always
    -e JVM_XMS=256m
    -e JVM_XMX=256m
    -e MODE=standalone
    -e PREFER_HOST_MODE=hostname
    -v /xxxxx/nacos_docker/init.d/custom.properties:/home/nacos/init.d/custom.properties
    -v /xxxxx/nacos_docker/logs:/home/nacos/logs
    nacos/nacos-server
    
  • 访问 http://localhost:8848
  • 输入 nacos/nacos登陆

新建配置内容

Spring cloud gateway nacos实现动态路由_第1张图片

内容如下

[{
    "id":"user-router",
    "predicates":[
      {
        "args":{
          "pattern": "/usr/**"
        },
        "name": "Path"
      }
    ],
    "filters": [
      {
        "name": "StripPrefix",
        "args": {
          "parts": "1"
        }
      }
    ],
    "uri": "lb://user-service"
}]

对应的yml内容如route部分

spring:
  application:
    name: dynamicgateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
      config:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-router
          uri: lb://user-service
          predicates:
            - Path=/usr/**
      filters:
        - StripPrefix=1 # 表示在转发时去掉usr

新建项目
因为使用了Spring cloud,Spring Cloud Alibaba,Nacos之间的版本依赖关系如下
版本依赖关系

新建DynamicGatewayRouteConfig

@Component
public class DynamicGatewayRouteConfig implements ApplicationEventPublisherAware {

    private String dataId = "gateway-router";

    private String group = "DEFAULT_GROUP";

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String serverAddr;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher applicationEventPublisher;

    private static final List ROUTE_LIST = new ArrayList();

    @PostConstruct
    public void dynamicRouteByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(serverAddr);
            configService.getConfig(dataId, group, 5000);
            configService.addListener(dataId, group, new Listener() {

                public void receiveConfigInfo(String configInfo) {
                    clearRoute();
                    try {
                        List gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
                        for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
                            addRoute(routeDefinition);
                        }
                        publish();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

    private void clearRoute() {
        for (String id : ROUTE_LIST) {
            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();
        }
    }

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

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

在nacos的route内容发生变化时会自动调用更新

bootstrap.yml内容如下

spring:
  application:
    name: dynamicgateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
 config:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
management:
  endpoints:
    web:
      exposure:
        include: '*'
 endpoint:
    health:
      show-details: always

具体代码
代码

你可能感兴趣的:(Spring cloud gateway nacos实现动态路由)