springcloud gateway基于nacos实现动态路由

1 创建动态路由表

在nacos上新增一个配置,专门用来配置网关路由信息,格式为json格式,如下所示:

{
    # 是否要更新路由表信息标识
    "refreshGatewayRoute":true,
    "routeList":[
        {
            # 唯一标识
            "id":"project1",
            "predicates":[
                {
                    "name":"Path",
                    "args":{
                        "pattern":"/project/**"
                    }
                }
            ],
            "filters":[
                {
                    "name":"StripPrefix",
                    "args":{
                        "parts":"1"
                    }
                }
            ],
            "uri":"lb://myproject",
            "order":0
        }
    ]
}

2 配置动态路由表信息

在网关的配置文件中添加路由表在nacos上的配置信息,包括server-addr、namespace、group和data-id,如下所示:

#动态路由相关配置
dynamic:
  route:
    data-id: dynamic-route
    group: ROUTE_GROUP
    server-addr: 127.0.0.1:8848
    namespace: b852f9b9-1d45-4dc7-a1c5-2c9169856836

3 创建实体类

  • 过滤器类
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * FilterEntity
 * @Description: 过滤器实体
 * @author: Steven_sf
 * @Date: 2020年02月14日
 */
public class FilterEntity {
    
    private String name;

    private Map<String, String> args = new LinkedHashMap<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, String> getArgs() {
        return args;
    }

    public void setArgs(Map<String, String> args) {
        this.args = args;
    }
}
  • 断言实体类
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * PredicateEntity
 * @Description: 断言
 * @author: Steven_sf
 * @Date: 2020年02月14日
 */
public class PredicateEntity {

    private String name;

    private Map<String, String> args = new LinkedHashMap<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, String> getArgs() {
        return args;
    }

    public void setArgs(Map<String, String> args) {
        this.args = args;
    }
}
  • 路由实体类
import java.util.ArrayList;
import java.util.List;

/**
 * RouteEntity
 * @Description: 路由实体
 * @author: Steven_sf
 * @Date: 2020年02月14日
 */
public class RouteEntity {

    //路由id
    private String id;

    //路由断言集合
    private List<PredicateEntity> predicates = new ArrayList<>();

    //路由过滤器集合
    private List<FilterEntity> filters = new ArrayList<>();

    //路由转发的目标uri
    private String uri;

    //路由执行的顺序
    private int order = 0;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public List<PredicateEntity> getPredicates() {
        return predicates;
    }

    public void setPredicates(List<PredicateEntity> predicates) {
        this.predicates = predicates;
    }

    public List<FilterEntity> getFilters() {
        return filters;
    }

    public void setFilters(List<FilterEntity> filters) {
        this.filters = filters;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }
}

4 添加监听器

添加监听器,监听动态路由表配置变化情况。

/**
 * DynamicRoutingConfig
 * @Description: 监听器
 * @author: Steven_sf
 * @Date: 2020年02月14日
 */
@Component
public class DynamicRoutingConfig implements ApplicationEventPublisherAware {


    @Value("${dynamic.route.server-addr}")
    private String serverAddr;

    @Value("${dynamic.route.namespace}")
    private String namespace;

    @Value("${dynamic.route.data-id}")
    private String dataId;

    @Value("${dynamic.route.group}")
    private String group;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher applicationEventPublisher;

    @Bean
    public void refreshRouting() throws NacosException {

        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
        properties.put(PropertyKeyConst.NAMESPACE, namespace);

            ConfigService configService = NacosFactory.createConfigService(properties);

            // 网关启动时,获取初始化路由信息,进行初始化操作
            initRoute(configService);

            // 监听路由信息变化情况
            configService.addListener(dataId, group, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {

                    // 获取动态刷新路由信息对标识:true-刷新路由信息;false-不刷新路由信息
                    boolean refreshGatewayRoute = JSONObject.parseObject(configInfo).getBoolean("refreshGatewayRoute");
                    if (refreshGatewayRoute) {
                        List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(configInfo).getString("routeList")).toJavaList(RouteEntity.class);

                        // 更新路由表
                        for (RouteEntity route : list) {
                            updateRoute(assembleRouteDefinition(route));
                        }
                    }
                }
            });


    }

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

    /**
     * 初始化路由信息
     * @param configService
     * @throws NacosException
     */
    private void initRoute(ConfigService configService) throws NacosException{
        String initRouteInfo = configService.getConfig(dataId, group, 60000);
        List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(initRouteInfo).getString("routeList")).toJavaList(RouteEntity.class);
        for (RouteEntity route : list) {
            saveRoute(assembleRouteDefinition(route));
        }
    }

    /**
     * 路由更新:先删除旧的路由信息,再保存新的路由信息
     * @param routeDefinition
     * @return
     */
    public void updateRoute(RouteDefinition routeDefinition){
        deleteRoute(routeDefinition);
        saveRoute(routeDefinition);
    }

    /**
     * 保存路由信息
     * @param routeDefinition
     * @return
     */
    public void saveRoute(RouteDefinition routeDefinition){

        try {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 删除路由信息
     * @param routeDefinition
     * @return
     */
    public void deleteRoute(RouteDefinition routeDefinition){

        try {
            this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 实体信息解析
     * @param routeDefinition
     * @return
     */
    public RouteDefinition assembleRouteDefinition(RouteEntity routeEntity) {

        RouteDefinition definition = new RouteDefinition();

        definition.setId(routeEntity.getId());

        List<PredicateDefinition> pdList = new ArrayList<>();
        for (PredicateEntity predicateEntity: routeEntity.getPredicates()) {
            PredicateDefinition predicateDefinition = new PredicateDefinition();
            predicateDefinition.setArgs(predicateEntity.getArgs());
            predicateDefinition.setName(predicateEntity.getName());
            pdList.add(predicateDefinition);
        }
        definition.setPredicates(pdList);

        List<FilterDefinition> fdList = new ArrayList<>();
        for (FilterEntity filterEntity: routeEntity.getFilters()) {
            FilterDefinition filterDefinition = new FilterDefinition();
            filterDefinition.setArgs(filterEntity.getArgs());
            filterDefinition.setName(filterEntity.getName());
            fdList.add(filterDefinition);
        }
        definition.setFilters(fdList);

        URI uri = UriComponentsBuilder.fromUriString(routeEntity.getUri()).build().toUri();
        definition.setUri(uri);

        return definition;
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值