又来给大家更文了。
微服务网关实战系列不知不觉已经第五篇了,该讲的基础知识已经讲过了,今天要来点进阶内容了:网关路由动态刷新。
我们知道,在 SCG 中,路由的配置有两种方式:代码配置和配置文件配置。
代码配置的是通过一个 bean 写入自定义的路由配置,就像这样:
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route((r) -> r.path("/user/**").uri("lb://user-api"))
.route((r) -> r.path("/order/**").uri("lb://order-api"))
.build();
}
复制代码
配置文件配置则是直接通过配置文件加载的方式读取配置内容,就像这样:
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
复制代码
当然,如果你引入了 spring-boot-starter-actuator 包你还可以拥有通过 OpenApi 方式修改路由的能力:

虽然以上三种方式都可以修改路由,但是在实际的工作中,前两种方式往往都是极不方便的,因为当我们想要修改某个路由的时候需要经过修改代码、重新打包、测试、部署、上线这一系列流程,随随便便可能半天的时间就去了,效率极低。
而第三种方式需要打开可观测点,这在线上环境中大概率不会一直打开,所以可以直接忽略。
所以对于以上这种需求,我们必然要提出一个解决方案进行路由的动态处理,这就是今天的正文内容了,我们开始吧!
1. 怎么修改路由?
我们在开头提到了三种修改路由的方式,前两种都是启动时加载,只有第三种是真正的动态加载,所以我们为了完成路由动态刷新的功能,可以很容易的想到是参考第三种的方式去进行路由动态修改,这个时候就需要我们阅读源码了。
我们先看查看修改路由接口的源码,在 IDEA 中你只需要在接口右键点击编辑就可以直接触达到代码位置:

此接口源码如下:
@PostMapping("/routes/{id}")
@SuppressWarnings("unchecked")
public Mono<ResponseEntity<Object>> save(@PathVariable String id, @RequestBody RouteDefinition route) {
return Mono.just(route).doOnNext(this::validateRouteDefinition)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() -> Mono.just(ResponseEntity.created(URI.create("/routes/" + id)).build()))))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
}
复制代码
通过这段源码可以看到一个有一个专门的 Bean 去处理路由的修改:routeDefinitionWriter,而我们只需要建造对应的 RouteDefinition 进行插入操作就可以了。
此时通过查看 RouteDefinition 的类定义可以看到它是这样的数据结构:
public class RouteDefinition {
private String id;
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@Valid
private List<FilterDefinition> filters = new ArrayList<>();
@NotNull
private URI uri;
private Map<String, Object> metadata = new HashMap<>();
private int order = 0;
}
复制代码
这个数据结构在网关系列讲解路由的那篇文章中我也提到过,很明显这是一个路由的数据结构,每个路由都有一个唯一的路由标识,可以很简单的联想

最低0.47元/天 解锁文章
161

被折叠的 条评论
为什么被折叠?



