【SpringCloud】实现动态网关路由-Nacos

本文记录一下如何使用 Gateway 搭建网关服务,实现动态路由的,帮助大家学习如何快速搭建网关服务,了解路由相关配置。

1、JSON路由配置

[
    {
        "id": "csdn",
        "uri": "https://blog.csdn.net",
        "predicates": [
            {
                "args": {
                    "pattern": "/csdn"
                },
                "name": "Path"
            }
        ]
    }
]

如图

2、配置路由存储方式

实现动态路由的关键是 RouteDefinitionRepository 接口,该接口存在一个默认实现InMemoryRouteDefinitionRepository,通过名字我们应该也知道,该实现是将配置文件中配置的信息加载到内存中。

为了更清楚处理过程及扩展,重写了 RouteDefinitionRepository 接口中的方法。

import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置路由存储方式
 *
 * @author H.Yang
 * @date 2022/10/14
 */
@Component
public class LocalRouteDefinitionRepository implements RouteDefinitionRepository {
    public final Map<String, RouteDefinition> routes = new ConcurrentHashMap();

    /**
     * 请注意,此方法很重要,从redis取路由信息的方法,官方核心包要用,核心路由功能都是从redis取的
     *
     * @return
     */
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        return Flux.fromIterable(routes.values());
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(r -> {
            routes.put(r.getId(), r);
            return Mono.empty();
        });

    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (routes.containsKey(id)) {
                routes.remove(id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));
        });
    }

    public void clear() {
        routes.clear();
    }
}

3、动态路由实现

编写态路由实现类,实现 ApplicationEventPublisherAware 接口。

服务启动时加载初始化路由配置,当配置发生变化的时候通过已添加的监听器监听 nacos 配置文件内的路由变化实现动态路由的功能。

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
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 reactor.core.publisher.Mono;

import java.net.URI;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * @author H.Yang
 * @date 2022/10/16
 */
@Slf4j
@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware, CommandLineRunner {

    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private LocalRouteDefinitionRepository localRouteDefinitionRepository;
    @Autowired
    private NacosConfigProperties nacosConfigProperties;

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


    @Override
    public void run(String... args) throws Exception {
        log.debug("启动时加载....");
        ConfigService configService = NacosFactory.createConfigService(nacosConfigProperties.assembleConfigServiceProperties());
        // 程序首次启动, 并加载初始化路由配置
        String configInfo = configService.getConfig("gateway-router.json", nacosConfigProperties.getGroup(), 5000);

        this.addRouteConfig(configInfo);

        // 添加监听器监听nacos配置文件内的路由变化
        configService.addListener("gateway-router.json", nacosConfigProperties.getGroup(), new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.debug("配置发生变化时加载....");
                
                refreshRouteConfig(configInfo);
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        });

    }

    /**
     * 刷新路由配置
     *
     * @param configInfo
     */
    private void refreshRouteConfig(String configInfo) {
        // 刷新配置时需要先清空缓存
        localRouteDefinitionRepository.clear();

        this.addRouteConfig(configInfo);
    }


    /**
     * 添加路由
     *
     * @param configInfo
     */
    private void addRouteConfig(String configInfo) {
        log.debug("动态添加路由配置...");

        List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
        for (RouteDefinition routeDefinition : routeDefinitions) {
            // 添加路由
            localRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
        }

        this.publish();

        log.debug("动态配置路由加载完成 {}", JSONUtil.toJsonStr(routeDefinitions));
    }


    /**
     * 发布
     */
    public void publish() {
        applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
    }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要基于Nacos实现Spring Cloud Gateway动态网关路由,可以按照以下步骤进行操作: 1. 添加依赖:在Spring Cloud Gateway项目的pom.xml文件中添加相应的依赖,包括spring-cloud-starter-gateway和spring-cloud-starter-alibaba-nacos-discovery等。 2. 配置Nacos注册中心:在application.properties或application.yml配置文件中添加Nacos注册中心的相关配置,包括Nacos服务器地址、命名空间、分组等信息。 3. 配置动态路由:创建一个RouteLocator Bean,并在其中使用Nacos的服务发现来定义动态路由规则。可以通过Nacos的配置中心来管理路由规则的动态更新。 ```java @Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("service_route", r -> r.path("/api/v1/**") .uri("lb://service-provider")) .build(); } } ``` 上述示例中,定义了一个名为service_route的路由规则,将请求路径以/api/v1/开头的请求转发到名为service-provider的微服务上。 4. 启动Gateway应用:启动Spring Cloud Gateway应用,它会自动从Nacos注册中心获取动态路由规则并进行路由转发。 5. 管理动态路由:使用Nacos的配置中心来管理动态路由规则。可以通过Nacos的控制台或API来添加、修改或删除路由规则,Gateway应用会自动更新并生效。 通过以上步骤,就可以基于Nacos实现Spring Cloud Gateway动态网关路由了。你可以根据实际需求和业务场景,添加更多的路由规则和配置。希望对你有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

旷野历程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值