SpringCloud Gateway 利用 Mysql 实现动态路由的方法

 更新时间:2021年02月19日 09:54:39   作者:稀土掘金  
这篇文章主要介绍了SpringCloud Gateway 利用 Mysql 实现动态路由的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

需求描述

标准网关动态路由功能是重要的一环,将路由、断言以及过滤器信息,持久化到 Mysql 中,通过配置后台页面实现路由、断言、以及过滤器等配置的增删改查。

Spring Cloud Gateway 路由及黑白名单实现背景 Spring Cloud 路由API

Spring Cloud Gateway 通过定义 RouteDefinitionRepository 来实现动态路由.

//保存路由缓存
public interface RouteDefinitionWriter {

  Mono<Void> save(Mono<RouteDefinition> route);

  Mono<Void> delete(Mono<String> routeId);

}
//获取路由缓存
public interface RouteDefinitionLocator {

  Flux<RouteDefinition> getRouteDefinitions();

}

Spring Cloud 配置文件路由加载方式

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {

  private final GatewayProperties properties;

  public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
   this.properties = properties;
  }

  @Override
  public Flux<RouteDefinition> getRouteDefinitions() {
   return Flux.fromIterable(this.properties.getRoutes());
  }

}

Spring Cloud 黑白名 FilterFactory

利用 Spring Cloud Gateway 声明的一个工厂接口 GatewayFilterFactory, 定义 黑白名单过滤器

BlacklistGatewayFilterFactory 类图

WhitelistGatewayFilterFactory 类图

动态路由设计 Spring Cloud Gateway 路由实体类

Spring Cloud Gateway 通过定义 RouteDefinition 类装载路由信息。

package org.springframework.cloud.gateway.route;

public class RouteDefinition {

  //路由 ID
  @NotEmpty
  private String id = UUID.randomUUID().toString();

  //断言数组
  @NotEmpty
  @Valid
  private List<PredicateDefinition> predicates = new ArrayList<>();

  //过滤器数组
  @Valid
  private List<FilterDefinition> filters = new ArrayList<>();

  // 路由地址
  @NotNull
  private URI uri;

  // 路由顺序
  private int order = 0;
}

数据库设计

路由表

drop table if exists gateway_route_t;

create table if not exists gateway_route_t
(
  ID     int auto_increment primary key,
  ROUTE_ID  varchar(255) not null comment '路由ID',
  ROUTE_ORDER int default 0 null comment '路由顺序',
  URI     varchar(255) not null comment '路由路径',
  VALID    int default 1 not null comment '是否有效:0-无效,1-有效',
  CREATE_USER varchar(200) null comment '创建人',
  CREATE_TIME datetime   null comment '创建时间',
  UPDATE_USER varchar(200) null comment '修改人',
  UPDATE_TIME datetime   null comment '修改时间',
  constraint idx_ROUTE_ID_index unique (ROUTE_ID)
) comment '网关路由信息表' charset = utf8;

路由参数表

drop table if exists gateway_route_param_t;

create table if not exists gateway_route_param_t
(
  ID     int auto_increment primary key,
  ROUTE_ID  varchar(255) not null comment '路由ID',
  PARAM_NAME varchar(255) not null comment '参数name',
  PARAM_KEY  varchar(255) not null comment '参数 key',
  PARAM_VALUE varchar(255) not null comment '参数 value',
  TYPE    int      not null comment '参数类型,1为 predicate,2为过 filter',
  VALID    int default 1 not null comment '是否有效:0-无效,1-有效',
  CREATE_USER varchar(200) null comment '创建人',
  CREATE_TIME datetime   null comment '创建时间',
  UPDATE_USER varchar(200) null comment '修改人',
  UPDATE_TIME datetime   null comment '修改时间'
) comment '网关路由参数表' charset = utf8;

create index idx_route_id on gateway_route_param_t (ROUTE_ID);

接口设计 接口定义

路由表配置接口

封装 gateway_route_t dao 层接口.

/**
 * <功能描述> 路由表接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteConfigService extends IService<RouteDomain>

路由参数表配置接口

封装 gateway_route_param_t dao 层接口.

/**
 * <功能描述> 路由参数表接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteParamConfigService extends IService<RouteParamDomain>

数据库路由服务接口

封装 路由表配置服务接口以及路由参数表配置接口, 对外层提供对数据库路由信息的操作.

/**
 * <功能描述> 数据库路由服务
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRoutePropertiesService

网关路由缓存接口

封装 RouteDefinitionRepository 接口,对外提供对网关路由缓存的刷新.

/**
 * <功能描述> 网关缓存路由服务
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IGatewayRouteService extends ApplicationEventPublisherAware

路由事件监听接口

配置需要监听路由变化的 service 实现

/**
 * <功能描述> 路由事件监听接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface RouteEventListener extends ApplicationListener<RefreshCacheEvent>

数据库黑白名单配置接口

/**
 * <功能描述> API Filter 接口定义
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IApiFilterService

网关白名单缓存接口

提供指定路由 API 白名单check 监听路由事件

/**
 * <功能描述> API 白名单缓存接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IApiCacheService extends RouteEventListener

路由参数执行校验接口

封装 提供路由参数的校验的接口.

/**
 * <功能描述> 路由参数校验
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteValidateExecutorService

接口类图 路由及黑白名单类图

断言及过滤器封装类图

集群缓存刷新事件处理策略类图

路由初始化设计 重载 PropertiesRouteDefinitionLocator

/**
 * <功能描述> 重写 PropertiesRouteDefinitionLocator bean
 * 将配置文件中的路由信息通过 MysqlRouteConfig 载入。
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
@Configuration
@AutoConfigureBefore({MysqlRouteConfig.class})
public class PropertiesRouteConfig {
  @Bean
  public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
      GatewayProperties properties) {
    return new PropertiesRouteDefinitionLocator(new GatewayProperties());
  }
}

定义 initMysqlRouteDefinition Bean 加载数据库及配置文件的路由配置

/**
 * <功能描述> 从Mysql中初始化路由信息
 * 覆盖配置文件中的路由信息
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
@Configuration
public class MysqlRouteConfig {
  private final IRoutePropertiesService routePropertiesService;
  private final IGatewayRouteService gatewayRouteService;

  public MysqlRouteConfig(IRoutePropertiesService routePropertiesService, IGatewayRouteService gatewayRouteService) {
    this.routePropertiesService = routePropertiesService;
    this.gatewayRouteService = gatewayRouteService;
  }

  /**
   * 初始化 gatewayProperties 中的 route
   *
   * @param gatewayProperties
   * @return
   */
  @Bean
  public List<RouteDefinition> initMysqlRouteDefinition(GatewayProperties gatewayProperties) {
    List<RouteDefinition> gatewayPropertiesRoutes = gatewayProperties.getRoutes();

    //初始化数据库路由信息
    List<RouteDefinition> routeDefinitionList = routePropertiesService.getRouteDefinitionList();
    if (CollectionUtils.isEmpty(gatewayProperties.getRoutes()) && CollectionUtils.isEmpty(routeDefinitionList)) {
      throw new BizBaseException(HprmcExceptionCode.ROUTE_NOT_FOUND);
    }

    Set<String> routeIds = routeDefinitionList.stream()
        .map(RouteDefinition::getId).collect(Collectors.toSet());
    if (gatewayPropertiesRoutes.stream().anyMatch(r -> routeIds.contains(r.getId()))) {
      throw new BizBaseException(HprmcExceptionCode.ROUTE_INIT_CONFLICT);
    }

    //将配置文件中的路由信息添加到 InMemoryRouteDefinitionRepository 成员变量中
    if (!CollectionUtils.isEmpty(gatewayPropertiesRoutes)) {
      gatewayPropertiesRoutes.forEach(gatewayRouteService::addInMemoryRouteRefresh);
    }

    //写到 InMemoryRouteDefinitionRepository 成员初始化缓存
    if (!CollectionUtils.isEmpty(routeDefinitionList)) {
      routeDefinitionList.forEach(gatewayRouteService::addInMemoryRouteRefresh);
    }
    return routeDefinitionList;
  }
}

到此这篇关于SpringCloud Gateway 利用 Mysql 实现动态路由的方法的文章就介绍到这了,更多相关SpringCloud Gateway 实现动态路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring强行注入和引用实例解析

    spring强行注入和引用实例解析

    这篇文章主要介绍了spring强行注入和引用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • SpringBoot集成I18n国际化文件在jar包外生效问题

    SpringBoot集成I18n国际化文件在jar包外生效问题

    这篇文章主要介绍了SpringBoot集成I18n国际化文件在jar包外生效问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Spring Boot项目中使用 TrueLicense 生成和验证License的详细步骤

    Spring Boot项目中使用 TrueLicense 生成和验证License的详细步骤

    这篇文章主要介绍了Spring Boot项目中使用 TrueLicense 生成和验证License,本文分步骤给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10
  • fastjson全局日期序列化设置导致JSONField失效问题解决方案

    fastjson全局日期序列化设置导致JSONField失效问题解决方案

    这篇文章主要介绍了fastjson通过代码指定全局序列化返回时间格式,导致使用JSONField注解标注属性的特殊日期返回格式失效问题的解决方案
    2023-01-01
  • SpringCloud Ribbon负载均衡工具使用

    SpringCloud Ribbon负载均衡工具使用

    Ribbon是Netflix的组件之一,负责注册中心的负载均衡,有助于控制HTTP和TCP客户端行为。Spring Cloud Netflix Ribbon一般配合Ribbon进行使用,利用在Eureka中读取的服务信息,在调用服务节点时合理进行负载
    2023-02-02
  • 解读controller层,service层,mapper层,entity层的作用与联系

    解读controller层,service层,mapper层,entity层的作用与联系

    这篇文章主要介绍了关于controller层,service层,mapper层,entity层的作用与联系,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • arthas jprofiler做复杂链路的调用分析

    arthas jprofiler做复杂链路的调用分析

    这篇文章主要为大家介绍了arthas jprofiler做复杂链路的调用分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Springboot自动装配实现过程代码实例

    Springboot自动装配实现过程代码实例

    这篇文章主要介绍了Springboot自动装配实现过程代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 详解mybatis批量插入10万条数据的优化过程

    详解mybatis批量插入10万条数据的优化过程

    这篇文章主要介绍了详解mybatis批量插入10万条数据的优化过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java开发或调用WebService的几种方式总结

    Java开发或调用WebService的几种方式总结

    java开发过程中,很多地方都会遇到数据传递,远程获取数据问题,这篇文章主要介绍了Java开发或调用WebService的几种方式的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06

最新评论