使用网关的目的
- 前端无需关注具体请求哪个微服务,由网关来控制。
- 网关统一拦截,可以做灰度/权限/限流/负载均衡等逻辑,无需每个微服务都重复实现这个逻辑
为什么不用nginx?
nginx支持以上所说的大部分功能,但是使用gateway能够更加灵活的进行扩展开发。
Spring cloud gateway
Spring cloud gateway最基础的功能是路由,每个路由最重要的参数是uri,predicates,filters,如下代码。
spring:
cloud:
gateway:
routes:
- id: test-service # 路由ID
uri: http://localhost:8080 # 路由地址
predicates: # 路由断言,需满足所有条件
- Path=/testurl
filters: # 过滤器
- StripPrefix=1
predicates决定了哪些请求会进入这个路由,uri则表示要转发到的地方,filters则是转发过程中要经过的一系列过滤器,这些filters也是我们用来实现扩展功能的地方,比如鉴权等。
接下来详细介绍下这三个参数
1. Predicates
官方提供了很多默认的predicate,也可以自行实现。
如上配置的Path对应PathRoutePredicateFactory(*RoutePredicateFactory,*就是参数的名字)。我们通过源码可以看到它就是做了正则匹配,但要注意这里不是通用的正则匹配,很多正则规则都不支持。
public Predicate<ServerWebExchange> apply(PathRoutePredicateFactory.Config config) {
...
return (exchange) -> {
// 获取path
PathContainer path = PathContainer.parsePath(exchange.getRequest().getURI().getRawPath());
// 正则匹配(不是普通的正则,是spring的正则)
Optional<PathPattern> optionalPathPattern = pathPatterns.stream().filter((pattern) -> {
return pattern.matches(path);
}).findFirst();
// 匹配到
if (optionalPathPattern.isPresent()) {
PathPattern pathPattern = (PathPattern)optionalPathPattern.get();
...
return true;
} else {
traceMatch("Pattern", config.getPatterns(), path, false);
return false;
}
};
}
多个Predicate的关系是and。具体的实现在RouteDefinitionRouteLocator。我们的网关就是重写了这个类,使得Predicate关系可以灵活的配置成and或者or。
private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
// 获取所有predicates
List<PredicateDefinition>