GateWay 动态路由(从nacos上取)

动态路由的好处

网关动态路可以从redis中取,或者nacos都可以。好处有:修了配置能够动态更新

依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <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>
        <!--        配置中心来做配置管理-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.7</version>
        </dependency>
    </dependencies>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

配置类

这里可以从nacos注入,我是直接写死了


@Configuration
public class DynamicRouteConfig {
    public static final String NACOS_SERVICE_ADDR="localhost:8848";
    public static final String NACOS_SERVICE_NAMESPACE="7990000d-2835-42d9-86a6-76d998d8c5ea";
    public static final String NACOS_ROUTE_DATA_ID="route.json";
    public static final String NACOS_SROUTE_GROUP="DEFAULT_GROUP";
}

监听类与初始化


import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;

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

@Service
@Slf4j
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
    @Resource
    private RouteDefinitionWriter routeDefinitionWriter;
    @Resource
    private RouteDefinitionLocator routeDefinitionLocator;

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

    public void delete(String id){
        try {
            log.info("gateway delete route id {}",id);
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        }catch (Exception e){

        }
    }

    public void updateList(List<RouteDefinition> definitions){
        log.info("gateway update route {}",definitions);
        List<RouteDefinition> routeDefinitionsExits = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
        if (!CollectionUtils.isEmpty(routeDefinitionsExits)){
            routeDefinitionsExits.forEach(routeDefinition ->{
                log.info("delete routeDefinition:{}",routeDefinition);
                delete(routeDefinition.getId());
            });
        }
        definitions.forEach(this::updateById);

    }

    private void updateById(RouteDefinition definition) {
        try {
            log.info("gateway update route {}",definition);
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));

        }catch (Exception e) {
            definition.getId();
            return;
        }
        try{
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));

        }catch (Exception e){

        }
    }

    public String addRoute(RouteDefinition definition){
        log.info("gateway add route {}",definition);
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }

}


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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

@Component
@Slf4j
@DependsOn("dynamicRouteConfig")
public class DynamicRouteServiceImolByNacos {
    @Resource
    private DynamicRouteServiceImpl dynamicRouteService;

    private ConfigService configService;


    @PostConstruct
    public void init(){
        log.info("gateway route init......");
        try {
            configService=initConfigService();
            if (configService == null){
                log.info("gateway initConfigService fail");
                return;
            }
            String configInfo = configService.getConfig(DynamicRouteConfig.NACOS_ROUTE_DATA_ID,
                    DynamicRouteConfig.NACOS_SROUTE_GROUP, 3000);
            if (StringUtils.isEmpty(configInfo)) {
              throw  new RuntimeException("ddd");
            }
            log.info("获取网关配置:\r\n{}",configInfo);
            List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);

            for (RouteDefinition definition : definitionList) {
                log.info("update route :{}",definition.toString());
                dynamicRouteService.addRoute(definition);
            }
        }catch (Exception e) {
            log.error("初始化网关路由时失败:",e);
        }

        dynamicRouteByNacosListener(DynamicRouteConfig.NACOS_ROUTE_DATA_ID,
                DynamicRouteConfig.NACOS_SROUTE_GROUP);
    }

    private void dynamicRouteByNacosListener(String dataId, String group) {
        try {
            configService.addListener(dataId, group, new Listener() {
                @Override
                public Executor getExecutor() {
                    log.info("getExecutor \r\n");
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("进行网关更新:\n\r{}",configInfo);
                    List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
                    log.info("update route :{}",definitionList.toString());
                    dynamicRouteService.updateList(definitionList);
                }
            });
        } catch (NacosException e) {
            log.error("从nacos 接受动态路由配置出错!!!:",e);
        }
    }

    private ConfigService initConfigService(){
        try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr",DynamicRouteConfig.NACOS_SERVICE_ADDR);
            properties.setProperty("namespace",DynamicRouteConfig.NACOS_SERVICE_NAMESPACE);
            return NacosFactory.createConfigService(properties);
        }catch (Exception e){
            log.error("初始化网关路由时失败:",e);
            return null;
        }
    }

}

效果

当nacos 路由文件修改之后,这里可以监听到。
在这里插入图片描述

总结

1-要想真正了解,需要了解Gateway源码。
2-了解一些,SPring 的反应式编程

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值