gateway配置mysql_SpringCloud Gateway 利用 Mysql 实现动态路由

需求描述

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

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

Spring Cloud 路由API

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

//保存路由缓存

public interface RouteDefinitionWriter {

Mono save(Mono route);

Mono delete(Mono routeId);

}

复制代码

//获取路由缓存

public interface RouteDefinitionLocator {

Flux getRouteDefinitions();

}

复制代码

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

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {

private final GatewayProperties properties;

public PropertiesRouteDefinitionLocator(GatewayProperties properties) {

this.properties = properties;

}

@Override

public Flux 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 predicates = new ArrayList<>();

//过滤器数组

@Valid

private List 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

复制代码

路由参数表配置接口

封装 gateway_route_param_t dao 层接口.

/**

* 路由参数表接口

*

* @author 20024322

* @date 2020/12/24 13:20

*/

public interface IRouteParamConfigService extends IService

复制代码

数据库路由服务接口

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

/**

* 数据库路由服务

*

* @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

复制代码

数据库黑白名单配置接口

/**

* 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 initMysqlRouteDefinition(GatewayProperties gatewayProperties) {

List gatewayPropertiesRoutes = gatewayProperties.getRoutes();

//初始化数据库路由信息

List routeDefinitionList = routePropertiesService.getRouteDefinitionList();

if (CollectionUtils.isEmpty(gatewayProperties.getRoutes()) && CollectionUtils.isEmpty(routeDefinitionList)) {

throw new BizBaseException(HprmcExceptionCode.ROUTE_NOT_FOUND);

}

Set 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;

}

}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值