Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,Spring Cloud Gateway 旨在为微服务架构提供一种简单而有效的统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,目标是替代 Netflix ZUUL,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre
)或之后(post
)执行业务逻辑。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.banmingi.nodeappgroupId>
<artifactId>parentartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
<artifactId>gatewayartifactId>
<packaging>jarpackaging>
<inceptionYear>2019-NowinceptionYear>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
dependency>
dependencies>
<licenses>
<license>
<name>Apache 2.0name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txturl>
license>
licenses>
<developers>
<developer>
<id>374564448id>
<name>banminginame>
<email>[email protected]email>
developer>
developers>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.6version>
<configuration>
<configurationFile>
${basedir}/src/main/resources/generator/generatorConfig.xml
configurationFile>
<overwrite>trueoverwrite>
<verbose>trueverbose>
configuration>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.17version>
dependency>
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapperartifactId>
<version>4.1.5version>
dependency>
dependencies>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>
com.banmingi.nodeapp.gateway.GatewayApplication
mainClass>
configuration>
plugin>
plugins>
build>
project>
特别注意:
starter-webflux
,所以这里 千万不要依赖 starter-web
javax.servlet:javax.servlet-api
server:
port: 9000
spring:
main:
allow-bean-definition-overriding: true
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
#让gateway从服务发现组件上面找到其他微服务并自动代理
enabled: true
# 暴露所有 actuator 端点
management:
endpoints:
jmx:
exposure:
include: '*'
# 健康检查展示详情
endpoint:
health:
show-details: always
**Route(路由):**Spring Cloud Gateway的元素基础,可简单理解成一条转发的规则。包含ID、目标URL、Predicate集合以及Filter集合。
**Predicate(谓词):**即java.util.Predicate,Spring Cloud Gateway使用Predicate实现路由的匹配条件。
**Filter(过滤器):**修改请求及响应。
路由匹配示例:
spring:
cloud:
gateway:
discovery:
locator:
#让gateway从服务发现组件上面找到其他微服务
enabled: true
routes:
- id: between_router
uri: lb://user-center
predicates:
- Path=/users/1
filters:
- AddRequestHeader=X-Request-Foo,Bar
官方提供的路由谓词工厂详解
Spring Cloud Gateway默认提供了一系列的路由谓词工厂,但如果这些内置的谓词工厂不能满足我们的需求,就需要编写自己的路由谓词工厂了。
**例如:**自定义路由工厂,使其在9:00~17:00这个期间才能访问。
配置:
spring:
cloud:
gateway:
discovery:
locator:
#让gateway从服务发现组件上面找到其他微服务
enabled: true
routes:
- id: between_router
uri: lb://user-center
predicates:
- TimeBetween=上午9:00,下午11:00
创建名为TimeBetweenRoutePredicateFactory的类,继承AbstractRoutePredicateFactory
注意这个类前缀为TimeBetween,与配置里面谓词的名字相一致,而且这个类一定要以RoutePredicateFactory结尾。
@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenConfig> {
public TimeBetweenRoutePredicateFactory() {
super(TimeBetweenConfig.class);
}
@Override
public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
LocalTime start = config.getStart();
LocalTime end = config.getEnd();
return exchange -> {
LocalTime now = LocalTime.now();
//时间处于 start 和 end 之间
return now.isAfter(start) && now.isBefore(end);
};
}
/**
* 控制 配置类和配置文件的映射关系和顺序
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
//映射
//上午9:00 下午5:00是Gateway的时间格式形式
//配置文件中的上午9:00对应配置实体类中的start,下午5:00对应end
return Arrays.asList("start","end");
}
}
@Data
public class TimeBetweenConfig {
private LocalTime start;
private LocalTime end;
}
局部过滤器
全局过滤器
过滤器的声明周期
自定义过滤器工厂的方式
编写一个过滤器工厂
**例如:**进入这个过滤器工厂时就打印一下日志。
配置:
spring:
cloud:
gateway:
discovery:
locator:
#让gateway从服务发现组件上面找到其他微服务
enabled: true
routes:
- id: between_router
uri: lb://user-center
predicates:
- TimeBetween=上午9:00,下午11:00
filters:
- PreLog=a,b
创建名为PreLogGatewayFilterFactory的类继承AbstractNameValueGatewayFilterFactory,
注意这个类前缀为PreLog,与配置里面filter的名字相一致,而且这个类一定要以GatewayFilterFactory结尾
@Slf4j
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return ((exchange,chain) -> {
log.info("请求进来了 = {},{}",config.getName(),config.getValue());
ServerHttpRequest modifiedRequest = exchange.getRequest()
.mutate()
.build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
return chain.filter(modifiedExchange);
});
}
}
**结论1:**Order越小越靠前执行
**结论4:**如需自行控制Order,可返回OrderedGatewayFilter
后面会讲到,再回来做总结
Spring Cloud Gateway监控
Spring Cloud Gateway排错、调试技巧总结
Spring Cloud Gateway限流详解