Spring Cloud Gateway的基础元素,可简单理解成一条转发规则。包含:路由ID、目标URL、Predicate集合以及Filter集合。
spring:
cloud:
gateway:
routes:
- id: server-center
uri: lb://server-center
predicates:
- Path=/sample/cloud/v1/server-center/**
filters:
- StripPrefix=4
复制代码
即java.util.function.Predicate这个接口,Gateway使用Predicate实现路由的匹配条件
与我们平时使用的Servlet编程模型里的过滤器概念类似,同样可以用于修改请求以及响应数据,可以利用Filter实现鉴权、访问日志记录,接口耗时记录等功能
Gateway Client发送请求给Spring Cloud Gateway,Gateway Handler Mapping会判断请求的路径是否匹配路由的配置,如果匹配则会进入Gateway Web Handler,Web Handler会读取路由上所配置的过滤器,然后将该请求交给过滤器去处理,最后转发到路由配置的微服务上。
这里使用IDEA的Spring Initializr进行项目的创建,到选择依赖这一步勾选gateway依赖,如下图:
网关组件一般都配合服务发现组件使用,我这里使用Nacos作为服务发现组件,具体的依赖如下(2.1.x为例):
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Greenwich.SR2version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
复制代码
然后编写配置文件内容如下:
server:
port: 8040
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
enabled: true
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
复制代码
完成以上步骤后,我们来启动这个网关服务,进行一个简单的测试,看看是否能将请求正常地转发到指定的微服务上。
此时有一个名为server-center的微服务,该微服务有一个按id获取用户信息的接口,接口路径为/users/{id}。
若通过网关服务来访问这个接口,要如何做呢?很简单,gateway配合服务发现组件使用时,会有一个默认的转发规则,如下:
${GATEWAY_URL}/{微服务名称}/{接口路径}
复制代码
按该规则得出来的具体url为:localhost:port/server-center/users/{id},gateway可以根据url上的微服务名称将访问请求转发到该微服务上。
predicates配置项必须有,且必须配置一个及以上的Predicate,但不一定非要配置Path,可以配置其他的Predicate,例如After、Before等,此时Path的默认值为/**
Spring Cloud Gateway的路由配置有两种形式,分别是路由到指定的URL以及路由到指定的微服务。
在这两种形式中,均支持访问路径的通配及精确匹配,在之前的示例中我们只使用了通配。这里将给出具体的配置示例,以此直观的了解这两种形式及不同匹配方式在配置上的区别。
通配,使用通配符/**进行匹配,示例:
spring:
cloud:
gateway:
routes:
- id: test_route
uri: http://www.xxx.com
predicates:
- Path=/**
复制代码
该配置使访问 GATEWAY_URL/** 时会转发到 www.xxx.com/
配置具体的接口路径即可,示例:
spring:
cloud:
gateway:
routes:
- id: test_route
uri: http://www.xxx.com/user/order/detail
predicates:
- Path=/user/order/detail
复制代码
该配置使访问 GATEWAY_URL/user/order/detail 时会转发到 ttp://www.xxx.com/user/order/…
通配,示例:
spring:
cloud:
gateway:
routes:
- id: server-center
uri: lb://server-center
predicates:
- Path=/**
复制代码
该配置使访问 GATEWAY_URL/** 时会转发到 server-center微服务的/** 精确匹配,示例:
spring:
cloud:
gateway:
routes:
- id: server-center
uri: lb://server-center/users/info
predicates:
- Path=/users/info
复制代码
该配置使访问 GATEWAY_URL/users/info 时会转发到 server-center微服务的/users/info。
前面提到过谓词是路由的判断条件,而路由谓词工厂就是作用到指定路由上的一堆谓词判断条件。在之前的示例里,我们就已经使用过路由谓词工厂了,就是自定义转发路径时所配置的Path。
Spring Cloud Gateway内置了众多路由谓词工厂,这些路由谓词工厂为路由匹配的判断提供了有力的支持,而我们之前所使用的Path就是内置的路由谓词工厂之一,用于判断当前访问的接口路径是否与该路由所配置的路径相匹配,若匹配则进行转发。
由于Gateway内置的路由谓词工厂比较多,篇幅有限就不在本文中介绍了,可以参考另一篇文章:
Spring Cloud Gateway内置了一系列的路由谓词工厂,但如果这些内置的路由谓词工厂不能满足业务需求的话,我们可以自定义路由谓词工厂来实现特定的需求。
例如有某个服务限制用户只允许在 09:00 - 17:00这个时间段内才可以访问,内置的路由谓词工厂是无法满足这个需求的,所以此时我们就需要自定义能够实现该需求的路由谓词工厂。
首先定义一个配置类,用于承载时间段的配置参数:
@Data
public class TimeBetweenConfig {
/**
* 开始时间
*/
private LocalTime start;
/**
* 结束时间
*/
private LocalTime end;
}
复制代码
然后定义一个路由谓词工厂,具体代码如下:
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory {
public TimeBetweenRoutePredicateFactory() {
super(TimeBetweenConfig.class);
}
public Predicate apply(TimeBetweenConfig config) {
return exchange -> {
LocalTime start = config.getStart();
LocalTime end = config.getEnd();
LocalTime now = LocalTime.now();
return now.isAfter(start) && now.isBefore(end);
};
}
public List shortcutFieldOrder() {
return Arrays.asList("start", "end");
}
}
复制代码
最后需要在配置文件中启用该路由谓词工厂,并且需要禁止gateway通过服务发现组件转发请求到其他的微服务,修改Gateway相关配置如下:
spring:
cloud:
gateway:
discovery:
locator:
enabled: false
routes:
- id: server-center
uri: lb://server-center
predicates:
- TimeBetween=上午9:00,下午5:00
复制代码
可以看到这里主要是配置了我们自定义的路由谓词工厂类名的前缀以及允许访问的时间段,这个时间格式不是随便配置的,而是Spring Cloud Gateway的默认时间格式,相关源码如下:
org.springframework.format.support.DefaultFormattingConversionService
复制代码
时间格式是可以注册的,关于时间格式注册的相关源码如下:
org.springframework.format.datetime.standard.DateTimeFormatterRegistrar
复制代码