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 实现动态路由内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解SpringCloudGateway内存泄漏问题

    SpringCloudGateway内存泄漏问题 项目完善差不多,在进入压力测试阶段期间,发现了gateway有内存泄漏问题,问题发现的起因是,当时启动一台gateway,一台对应的下游应用服务,在压力测试期间,发现特别不稳定,并发量时高时低,而且会有施压机卡住的现象,然后找到容器对应的宿主机,并使用container stats命令观察内存,经过观察发现,压力测试时内存会暴涨,并由于超过限制最大内存导致容器挂掉(这里由于用的swarm所以会自动选择节点重启)最终发现由于之前测试服务器配置低,所

  • 详解SpringCloud Finchley Gateway 统一异常处理

    SpringCloud Finchley Gateway 统一异常处理 全文搜索[@@]搜索重点内容标记 1 . 问题:使用SpringCloud Gateway时,会出现各种系统级异常,默认返回HTML. 2 . Finchley版本的Gateway,使用WebFlux形式作为底层框架,而不是Servlet容器,所以常规的异常处理无法使用 翻阅源码,默认是使用DefaultErrorWebExceptionHandler这个类实现结构如下: 可以实现参考DefaultErrorWebExcep

  • SpringCloud Gateway跨域配置代码实例

    这篇文章主要介绍了SpringCloud Gateway跨域配置代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Springboot版本:2.1.8.RELEASE SpringCloud版本:Greenwich.SR2 yml配置: spring: cloud: gateway: globalcors: cors-configurations: '[/**]': # 允许携带认证信息 # 允许跨域的源(网站域名/ip),设置*为全部

  • springcloud gateway聚合swagger2的方法示例

    问题描述 在搭建分布式应用时,每个应用通过nacos在网关出装配了路由,我们希望网关也可以将所有的应用的swagger界面聚合起来.这样前端开发的时候只需要访问网关的swagger就可以,而不用访问每个应用的swagger. 框架 springcloud+gateway+nacos+swagger 问题分析 swagger页面是一个单页面应用,所有的显示的数据都是通过和springfox.documentation.swagger.web.ApiResponseController进行数据交互,

  • 详解SpringCloud Gateway之过滤器GatewayFilter

    在Spring-Cloud-Gateway之请求处理流程文中我们了解最终网关是将请求交给过滤器链表进行处理,接下来我们阅读Spring-Cloud-Gateway的整个过滤器类结构以及主要功能 通过源码可以看到Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,下来我依次阅读接口的主要实现功能. GatewayFilterChain 类图 代码 /** * 网关过滤链表接口 * 用

  • SpringCloud Finchley Gateway 缓存请求Body和Form表单的实现

    在接入Spring-Cloud-Gateway时,可能有需求进行缓存Json-Body数据或者Form-Urlencoded数据的情况. 由于Spring-Cloud-Gateway是以WebFlux为基础的响应式架构设计,所以在原有Zuul基础上迁移过来的过程中,传统的编程思路,并不适合于Reactor Stream的开发. 网络上有许多缓存案例,但是在测试过程中出现各种Bug问题,在缓存Body时,需要考虑整体的响应式操作,才能更合理的缓存数据 下面提供缓存Json-Body数据或者Form

  • springboot2.0和springcloud Finchley版项目搭建(包含eureka,gateWay,Freign,Hystrix)

    前段时间spring boot 2.0发布了,与之对应的spring cloud Finchley版本也随之而来了,两者之间的关系和版本对应详见我这边文章:spring boot和spring cloud对应的版本关系 项目地址:spring-cloud-demo spring boot 1.x和spring cloud Dalston和Edgware版本搭建的微服务项目现在已经很流行了,现在很多企业都已经在用了,这里就不多说了. 使用版本说明: spring boot 2.0.x spring

  • SpringCloud Gateway使用redis实现动态路由的方法

    1. 将 actuator 端点暴露出来 management: endpoints: web: exposure: include: "*" 2. redis 配置 https://www.jb51.net/article/203766.htm 3. 将原内存路由持久化到 redis @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { /** * h

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

    需求描述 标准网关动态路由功能是重要的一环,将路由.断言以及过滤器信息,持久化到 Mysql 中,通过配置后台页面实现路由.断言.以及过滤器等配置的增删改查. Spring Cloud Gateway 路由及黑白名单实现背景 Spring Cloud 路由API Spring Cloud Gateway 通过定义 RouteDefinitionRepository 来实现动态路由. //保存路由缓存 public interface RouteDefinitionWriter { Mono<Vo

  • 基于Nacos实现Spring Cloud Gateway实现动态路由的方法

    简介 该文档主要介绍以Nacos为配置中心,实现Spring Cloud GateWay 实现动态路由的功能.Spring Cloud Gateway启动时候,就将路由配置和规则加载到内存里,无法做到不重启网关就可以动态的对应路由的配置和规则进行增加,修改和删除.通过nacos的配置下发的功能可以实现在不重启网关的情况下,实现动态路由. 集成 Spring Cloud GateWay集成 spring-cloud-starter-gateway:路由转发.请求过滤(权限校验.限流以及监控等) s

  • vue里面v-bind和Props 利用props绑定动态数据的方法

    如下所示: <add v-bind:子组件的值="父组件的属性"></add> <div id="app"> <add v-bind:btn="h"></add> </div> <script> var vm = new Vue({ el: '#app', data: { h: "hello" }, components: { "ad

  • vue 实现动态路由的方法

    很多时候我们在项目的路由都是在前端配置好的 但是有的时候为了进行全面的权限控制,会需要后台给出路由表,前端再渲染.不用在前端配置. 下面主要讲一下思路 1.和后台小哥哥沟通好数据,把我们前端配置的路由表数据给他,他就能看懂了 2.拿到数据需要我们自己再处理 路由中的component后台是给不了的,这里我们只需要后台小哥哥按照我们提供的前端component路径给数据,我们循环加载就可以了 //view就是后台给的数据 return () => import(`@/view/modules/${

  • Centos7 利用LVM实现动态扩容的方法

    摘要:最近项目组里来了很多新人,对linux分区及各种应用使用的分区不了解,导致测试数据库时突然发现某一个分区被写满了,不得不重装OS.实在看不下去了,特此分享我的一些利用LVM实现动态扩容的心得,希望对大家有帮助. 知识储备: LVM是逻辑盘卷管理(Logical VolumeManager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的灵活性.通过LVM系统管理员可以轻松管理磁盘分区,如:将若干个磁盘分区连接为一个整块

  • vue iview实现动态路由和权限验证功能

    github上关于vue动态添加路由的例子很多,本项目参考了部分项目后,在iview框架基础上完成了动态路由的动态添加和菜单刷新.为了帮助其他需要的朋友,现分享出实现逻辑,欢迎一起交流学习. Github地址 iview-dynamicRouter 实现目标 客户端从服务端拿到路由和权限数据后,刷新项目的路由和菜单列表,并进行权限控制. 项目基础 基础框架: iview组件库官方模板项目 iview-admin 的template分支项目,此项目为 iview-admin 的基础框架代码.项目地

  • Nginx gateway集群和动态网关的实现思路

    目录 基于nginx部署gateway集群 动态Gateway 使用数据库实现动态路由 网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能,提供路由请求.鉴权.监控.缓存.限流等功能.无论你查看任何一个微服务项目架构,你都会发现在客户端和服务器端之间有一个网关,移动端的任何请求都必须经过网关才能到达服务端. 网关怎么实现集群:使用nginx实现. 基于nginx部署gateway集群 1.将网关项目多个部署启动例如:网关1 127.0.0.1:81网关1 127.0.0

  • MySQL数据库改名的详细方法教程

    目录 前戏 被取消的命令 mysqldump 导入导出 改整库的表名 古老的方案 总结 前戏 有时候生产环境是以项目来命名,有时候会出现更名情况,其实如何安全的更改数据库名,是个非常棘手的问题,特别是针对 MySQL 来数据库来说 被取消的命令 MySQL 之前提供了一个 rename database db_old to db_new 的命令来直接对数据库改名,可能由于实现的功能不完备(比如,这条命令可能是一个超大的事务,或者是由于之前的表很多还是 MyISAM 等),后来 的版本直接取消了这

  • SpringCloud Gateway动态路由配置详解

    目录 路由 动态 路由模型实体类 动态路径配置 路由模型JSON数据 路由 gateway最主要的作用是,提供统一的入口,路由,鉴权,限流,熔断:这里的路由就是请求的转发,根据设定好的某些条件,比如断言,进行转发. 动态 动态的目的是让程序更加可以在运行的过程中兼容更多的业务场景. 涉及到两个服务,一个是门户服务(作用是提供给运营人员管理入口--包括:管理路由.绑定路由),一个是网关服务(gateway组件,为门户服务提供:查询路由信息.添加路由.删除路由.编辑路由接口). 路由模型实体类 /*

随机推荐