Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gateway动态路由似乎没有移除废弃路由规则的这个功能? #15

Open
hechaoqi123 opened this issue Nov 5, 2020 · 0 comments

Comments

@hechaoqi123
Copy link

hechaoqi123 commented Nov 5, 2020

gateway模块动态路由的实现方式似乎没有删除废弃路由的逻辑。我做了如下改造,不知道是否可行?

package com.example.gateway.config.route;

import com.alibaba.fastjson.JSONObject;
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.example.gateway.config.NacosGatewayProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.DependsOn;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

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


/**
 * @author hcq
 * @date 2020/11/4 19:31
 */
@Slf4j
@Component
@DependsOn({"nacosProperties"})
public class DynamicRouteConfig implements ApplicationEventPublisherAware {

    /**
     * 路由规则仓库
     */
    private final RouteDefinitionRepository definitionRepository;

    /**
     * 发布Application事件
     */
    private ApplicationEventPublisher publisher;

    /**
     * NacosConfig Client用于监听Nacos配置变更
     */
    private ConfigService configService;

    private DynamicRouteConfig(RouteDefinitionRepository definitionRepository) {
        this.definitionRepository = definitionRepository;
    }

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

    @PostConstruct
    public void init() {
        // 初始化Nacos配置的路由规则,并获取NacosClient
        configService = initConfig();
        // 监听Nacos配置文件
        dynamicRouteByNacosListener(NacosGatewayProperties.NACOS_ROUTE_DATA_ID, NacosGatewayProperties.NACOS_ROUTE_GROUP);
    }

    /**
     * 初始化NacosRoutes
     */
    private ConfigService initConfig() {
        log.info("gateway route init...");
        ConfigService configService = null;
        try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr", NacosGatewayProperties.NACOS_SERVER_ADDR);
            properties.setProperty("namespace", NacosGatewayProperties.NACOS_NAMESPACE);
            configService = NacosFactory.createConfigService(properties);
            if (configService == null) {
                log.warn("initConfigService fail");
                throw new IllegalArgumentException("initConfigService fail");
            }
            String configInfo = configService.getConfig(NacosGatewayProperties.NACOS_ROUTE_DATA_ID, NacosGatewayProperties.NACOS_ROUTE_GROUP, NacosGatewayProperties.DEFAULT_TIMEOUT);
            // 初始化路由规则
            if (StringUtils.isNotBlank(configInfo)) {
                updateRouteRule(configInfo);
            }
        } catch (Exception e) {
            log.error("初始化网关路由时发生错误", e);
        }
        return configService;
    }

    /**
     * 根据Nacos中配置的路由规则json串更新路由规则
     *
     * @param routesStr Nacos中配置的路由规则json串
     */
    private void updateRouteRule(String routesStr) {
        System.out.println(this);
        log.info("更新gateway路由规则\n\r{}", routesStr);
        definitionRepository.getRouteDefinitions().collectMap(RouteDefinition::getId).subscribe(oldRoutes -> {
            List<RouteDefinition> nowRoutes = JSONObject.parseArray(routesStr, RouteDefinition.class);
            // 删除原有规则
            for (RouteDefinition oldRoute : oldRoutes.values()) {
                log.info("gateway remove route {}", oldRoute);
                definitionRepository.delete(Mono.just(oldRoute.getId())).subscribe();
            }
            // 加载配置文件中的规则
            for (RouteDefinition route : nowRoutes) {
                log.info("gateway add route {}", route);
                definitionRepository.save(Mono.just(route)).subscribe();
            }
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        });
    }

    /**
     * 监听Nacos下发的动态路由配置
     *
     * @param dataId 路由规则
     * @param group  路由规则group
     */
    private void dynamicRouteByNacosListener(String dataId, String group) {
        try {
            DynamicRouteConfig routeConfig = this;
            configService.addListener(dataId, group, new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println(this);
                    System.out.println(routeConfig);
                    routeConfig.updateRouteRule(configInfo);
                }

                @Override
                public Executor getExecutor() {
                    log.info("getExecutor\n\r");
                    return null;
                }
            });
        } catch (NacosException e) {
            log.error("从nacos接收动态路由配置出错!!!", e);
        }
    }


}
@hechaoqi123 hechaoqi123 changed the title gateway动态路由移除已有的路由规则 gateway动态路由似乎没有移除废弃路由规则的这个功能? Nov 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant