SpringCloudGateway+nacos实现动态路由网关配置

动态网关配置

一、Maven依赖

<!-- 网关依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- nacos注册中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- nacos配置中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 简化set/get -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<!-- 支持yml、properties文件提示 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<!-- yaml解析包 -->
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
</dependency>

二、创建配置提示

1、DynamicRouteProperties类
package com.ksaas.cloud.gateway.config;

import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 包含 动态路由配置 的属性
 *
 * @author kylin
 * @see DynamicRouteConfiguration
 * @since 1.0.0
 */
@Data
@Component
@ConfigurationProperties(prefix = "ksaas.dynamic.route")
@ConditionalOnBean(DynamicRouteConfiguration.class)
public class DynamicRouteProperties {
    /**
     * nacos 配置管理  dataId
     */
    private String dataId;
    /**
     * nacos 配置管理 group
     */
    private String group;
    /**
     * nacos 服务地址
     */
    private String ipAddr;

    /**
     * 启动动态路由的标志,默认关闭
     */
    private boolean enabled = false;
}

2、创建yml参数规则

在resources/MATA-INFO下创建spring-configuration-metadata.json

{
  "groups": [
    {
      "sourceType": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration",
      "name": "动态路由配置属性",
      "type": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration"
    }
  ],
  "hints": [
    {
      "name": "ksaas.dynamic.route.enabled",
      "values": [
        {
          "value": true
        },
        {
          "value": false
        }
      ]
    }
  ],
  "properties": [
    {
      "sourceType": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration",
      "name": "ksaas.dynamic.route.dataId",
      "type": "java.lang.String",
      "desc": "dataId specified in Nacos configuration management"
    },
    {
      "sourceType": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration",
      "name": "ksaas.dynamic.route.group",
      "type": "java.lang.String",
      "desc": "group specified in Nacos configuration management"
    },
    {
      "sourceType": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration",
      "name": "ksaas.dynamic.route.ipAddr",
      "type": "java.lang.String",
      "desc": "nacos host address"
    },
    {
      "sourceType": "com.ksaas.cloud.gateway.config.DynamicRouteConfiguration",
      "name": "ksaas.dynamic.route.enabled",
      "type": "java.lang.Boolean",
      "desc": "Flag that enables dynamic route"
    }
  ]
}

三、配置动态路由拉取配置类

####1、yaml读取工具

package com.ksaas.cloud.gateway.util;

import org.yaml.snakeyaml.Yaml;

/**
 * Yaml 工具
 *
 * @author kylin
 */
public abstract class YamlHelper {

    private YamlHelper() {}
    public static Yaml getInstance() {
        return InnerClass.YAML;
    }
    
    private static class InnerClass {
        private static final Yaml YAML = new Yaml();
    }
}

2、configuration类
package com.ksaas.cloud.gateway.config;

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.AbstractListener;
import com.alibaba.nacos.api.exception.NacosException;
import com.ksaas.cloud.gateway.util.YamlHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.annotation.Configuration;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 动态路由配置
 *
 * @author kylin
 * @see route\example.yml  动态路由yml内容格式参考
 * @see DynamicRouteProperties 动态路由参数配置说明
 * @since 1.0.0
 */

@Slf4j
@Configuration
@ConditionalOnProperty(name = "ksaas.dynamic.route.enabled", matchIfMissing = true)
public class DynamicRouteConfiguration {

    private DynamicRouteProperties bean;
    private RouteDefinitionWriter writer;
    private ApplicationEventPublisher publisher;

    public DynamicRouteConfiguration(DynamicRouteProperties bean, RouteDefinitionWriter writer, ApplicationEventPublisher publisher) {
        this.bean = bean;
        this.writer = writer;
        this.publisher = publisher;
    }

    @PostConstruct
    private void init() {
        Assert.notNull(bean.getDataId(), "ksaas.dynamic.route.dataId null异常");
        Assert.notNull(bean.getGroup(), "ksaas.dynamic.route.group is null异常");
        Assert.notNull(bean.getIpAddr(), "ksaas.dynamic.route.ipAddr is null异常");
        dynamicRouteByNacosListener();
    }

    private void dynamicRouteByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(bean.getIpAddr());
            String content = configService.getConfigAndSignListener(
                    bean.getDataId(),
                    bean.getGroup(),
                    5000,
                    new AbstractListener() {
                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            updateConfig(configInfo);
                        }
                    });
            updateConfig(content);
        } catch (NacosException e) {
            log.error("nacos 获取动态路由配置和监听异常", e);
        }
    }

    private void updateConfig(String content) {
        log.info("nacos 动态路由更新: {}", content);
        try {
            getRouteDefinitions(content).forEach(routeDefinition -> {

                log.info("动态路由配置: {}", routeDefinition);
                writer.delete(Mono.just(routeDefinition.getId()));
                writer.save(Mono.just(routeDefinition)).subscribe();
                publisher.publishEvent(new RefreshRoutesEvent(this));

            });
        } catch (Exception e) {
            log.error("更新动态路由配置异常: ", e);
        }
    }

    private List<RouteDefinition> getRouteDefinitions(String content) {
        // 如果文件是json,这里则直接把内容转会为json即可
        return JSON.parseArray(JSON.toJSONString(
                YamlHelper.getInstance().load(content)
        ), RouteDefinition.class);
    }

}

四、配置bootstrap.yml

nacos 2.2.0 及以下版本配置文件必须是bootstrap级别,不然只会找localhost:8848地址

server:
  port: 9000
spring:
  application:
    # 应用名称
    name: spring-gateway
  cloud:
    # 使用 Naoos 作为服务注册发现、配置中心
    nacos:
      server-addr: 192.168.1.150:8848
    # 路由网关配置
    gateway:
      # 设置与服务注册发现组件结合,这样可以采用服务名的路由策略
      discovery:
        locator:
          enabled: true
# 自定义动态路由配置,对应nacos配置列表参数
ksaas:
  dynamic:
    route:
      dataId: gateway_dynamic_route_config
      group: refresh_gateway_dynamic_route_config
      ipAddr: ${spring.cloud.nacos.server-addr}
      enabled: true
# 配置日志级别,方别调试
logging:
  level:
    org.springframework.cloud.gateway: debug

五、创建规则

直接在nacos配置中心,创建即可,dataId 和 group创建对应的yml文件即可

  • 想做成json,可以直接把下面内容去网上转换位json即可
- id: route1
  filters:
    - args:
        parts: 1
      name: StripPrefix
  predicates:
    - args:
        pattern: /consumer-h/**
      name: Path
  uri: lb://consumer-h

- id: route2
  filters:
    - args:
        parts: 1
      name: StripPrefix
  predicates:
    - args:
        pattern: /lilei/**
      name: Path
  uri: lb://nacos-test

- id: route3
  filters:
    - args:
        parts: 1
      name: StripPrefix
  predicates:
    - args:
        pattern: /lilei4/**
      name: Path
  uri: https://www.baidu.com/

补充文件说明:

  • 如果服务名和路由相同时
    • 可不用配置动态路由,nocas会自动做好路由
    • 需要配置:spring.cloud.gateway.discovery.locator.enabled=true
  • 如果服务名和路由不同时
    • 需要自己在nacos配置管理创建一个yml格式的配置,创建时的参数根据自己的配置设定来创建{@link DynamicRouteConfigBean}
  • 动态路由 yml配置文件说明
    • id:采用自定义路由 ID(有固定用法,不同的 id 有不同的功能,详见:https://cloud.spring.io/spring-cloud-gateway/2.0.x/single/spring-cloud-gateway.html#gateway-route-filters)

    • filters:url过滤器,例如添加请求参数,删除前缀等,参考接口:GatewayFilterFactory

    • predicates:翻译过来是“谓词”的意思,必须,主要作用是匹配用户的请求,有很多种用法,参考接口:GatewayPredicate

    • uri:采用 LoadBalanceClient 方式请求,以 lb:// 开头,后面的是注册在 Nacos 上的服务名

      gateway:

      设置与服务注册发现组件结合,这样可以采用服务名的路由策略

      discovery:
      locator:
      enabled: true

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值