gateway配置mysql_Gateway路由配置从数据库或Redis获取

本文介绍了如何通过实现RouteDefinitionRepository接口,使SpringCloud Gateway的路由配置能够从MySQL数据库中动态获取和更新,从而避免因配置更改而需要重启Gateway导致的服务中断问题。
摘要由CSDN通过智能技术生成

目前SpringCloud Gateway只支持配置文件yml、properties和配置文件@Configuration的方式配置路由。这种方式有弊端,就是如果需要变更路由信息,修改路由规则,然后重启Gateway,修改或增加的路由规则才会生效。如果出现该问题,在Gateway重启的这段时间里,所有接入Gateway服务的应用都不可用。这肯定是不可行的。

Gateway默认的配置

¶yml配置文件

255967fc2f5026f89a5f318c462db691.png

¶@Configuration

436143e5ed6a2e7e5e67aa8749f56649.png

路由初始化

不管是什么方式配置路由,这些配置最后都会被封装到RouteDefinition中1

2

3

4

5

6

7

8

9

10

11

12

13

14

15public class RouteDefinition{

private String id;

@NotEmpty

@Valid

private List predicates = new ArrayList<>();

@Valid

private List filters = new ArrayList<>();

@NotNull

private URI uri;

private Map metadata = new HashMap<>();

private int order = 0;

public RouteDefinition(){

}

...

}

一个路由配置就是一个RouteDefinition对象,一个RouteDefinition对应一个ID,如果不设置,默认为uuid,所有路由信息在系统启动的时候被加载进内存里

0d0efefaa66c236be0fe7120c499e900.png

如图框住的部分就是加载yml文件,它返回PropertiesRouteDefinitionLocator对象,该对象实现RouteDefinitionLocator接口,该接口是路由的装载器1

2

3

4

5public interface RouteDefinitionLocator{

Flux getRouteDefinitions();

}

该接口只有一个方法,就是获取路由配置,该接口有多个实现类,分别对应不同的配置路由的方式

e66bca60799a3a061498c7cb8eabd279.pngCachingRouteDefinitionLocator -RouteDefinitionLocator包装类, 缓存目标RouteDefinitionLocator 为routeDefinitions提供缓存功能

CompositeRouteDefinitionLocator -RouteDefinitionLocator包装类,组合多种 RouteDefinitionLocator 的实现,为 routeDefinitions提供统一入口

PropertiesRouteDefinitionLocator-从配置文件(GatewayProperties 例如,YML / Properties 等 ) 读取RouteDefinition

DiscoveryClientRouteDefinitionLocator-从注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等 )读取RouteDefinition

RouteDefinitionRepository-从存储器( 例如,内存 / Redis / MySQL 等 )读取RouteDefinition

初始化顺序是配置文件加载初始化 PropertiesRouteDefinitionLocator–>CompositeRouteDefinitionLocator

存储器中加载初始化RouteDefinitionRepository–>CompositeRouteDefinitionLocator

注册中心加载初始化DiscoveryClientRouteDefinitionLocator–>CompositeRouteDefinitionLocator

而使用存储器中初始化的条件是,没有定义RouteDefinitionRepository1

2

3

4

5@Bean

@ConditionalOnMissingBean(RouteDefinitionRepository.class)

public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository(){

return new InMemoryRouteDefinitionRepository();

}

路由配置从数据库中获取

因此,我们可以通过实现RouteDefinitionRepository接口来自定义路由配置的获取方式

¶实现RouteDefinitionRepository接口1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59@Component

public class DBARouteDefinitionRepository implements RouteDefinitionRepository{

@Resource

private GatewayDao gatewayDao;

@Override

public Flux getRouteDefinitions(){

List gatewayRouteEntityList = getRouteConfig();

return Flux.fromIterable(gatewayRouteEntityList);

}

private List getRouteConfig(){

List routesEntities = gatewayDao.queryAllRoutes();

List definitions = new ArrayList<>();

//组装RouteDefinition

for (RoutesEntity entity : routesEntities) {

RouteDefinition definition = new RouteDefinition();

Map predicateParams = new HashMap<>();

PredicateDefinition predicate = new PredicateDefinition();

Map filterParams = new HashMap<>();

FilterDefinition filter = new FilterDefinition();

URI uri = UriComponentsBuilder.fromHttpUrl(entity.getUri()).build().toUri();

predicate.setName("Path");

predicateParams.put("pattern",entity.getPredicates());

predicate.setArgs(predicateParams);

//过滤暂时不写

//filter.setName("StripPrefix");

//TODO 动态过滤

definition.setPredicates(Arrays.asList(predicate));

//definition.setFilters();

definition.setUri(uri);

definition.setId(entity.getRouteId());

definitions.add(definition);

}

return definitions;

}

@Override

public Mono save(Mono route){

return null;

}

@Override

public Mono delete(Mono routeId){

return null;

}

}

¶动态路由1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36@Service

public class DBARouteConfigService implements ApplicationEventPublisherAware{

@Resource

private GatewayDao gatewayDao;

private ApplicationEventPublisher applicationEventPublisher;

public int add(RoutesEntity entity){

gatewayDao.create(entity);

applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));

return 1;

}

public int delete(String routeId){

gatewayDao.deleteByRouteId(routeId);

applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));

return 1;

}

public int update(RoutesEntity entity){

gatewayDao.updateRouteById(entity);

applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));

return 1;

}

/**

* 发布事件

* @param applicationEventPublisher

*/

@Override

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){

this.applicationEventPublisher = applicationEventPublisher;

}

}

在数据库中修改删除路由配置,然后再执行一下RefreshRoutesEvent事件,即可刷新路由配置,无需重启,立刻生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值