Spring Gateway功能特性
Spring Gateway是Spring Cloud生态系统中的一个项目,用于构建基于Spring Boot的微服务架构中的API网关。API网关在微服务架构中扮演着重要的角色,它可以处理请求的路由、负载均衡、安全性、限流、熔断等方面的任务。
以下是关于Spring Cloud Gateway的一些主要特点和功能:
- 动态路由: Spring Cloud Gateway支持基于配置的动态路由,允许在运行时添加、删除或修改路由规则,而无需重新启动网关服务。
- 断言和过滤器: 路由规则由一组断言和过滤器组成。断言用于匹配请求,而过滤器用于在请求被路由到目标地址之前或之后执行额外的逻辑。
- 集成Spring生态系统: Spring Cloud Gateway紧密集成了Spring Boot、Spring WebFlux和Spring Cloud,可以利用这些框架提供的强大功能。
- 负载均衡: 支持通过服务发现进行负载均衡,可以将请求动态路由到后端的多个实例中,以实现更好的性能和高可用性。
- 断路器模式: 集成了熔断器模式,可以防止故障的扩散,并在后端服务不可用时提供降级处理。
- WebSockets支持: 支持WebSocket协议,允许处理实时通信的场景。
- 集成OAuth2和认证: 提供了集成OAuth2和认证的功能,可以确保安全地处理外部请求。
- 全局过滤器: 支持全局过滤器,这些过滤器会在请求进入网关或者离开网关时执行,可用于日志记录、安全性检查等全局任务。
- 响应体重写: 允许修改响应体,比如重写响应内容、添加响应头等。
- 易于扩展: 提供了易于扩展的机制,可以自定义断言和过滤器,以满足特定的需求。
总体而言,Spring Cloud Gateway是一个灵活、强大的API网关,适用于构建微服务架构中的前端路由和代理服务。通过其丰富的功能和集成的Spring生态系统,可以有效地管理和保护你的微服务。
什么是Spring WebFlux?
Spring WebFlux是Spring Framework 5引入的一种响应式编程的框架,用于构建异步、非阻塞、响应式的应用程序。它提供了一种基于反应式流(Reactive Streams)的编程模型,支持异步处理HTTP请求和响应。
主要特点包括:
- 响应式编程模型: Spring WebFlux采用响应式编程模型,允许构建异步、非阻塞的应用程序。这意味着它可以处理大量的并发请求,提供更好的性能和可伸缩性。
- 非阻塞 I/O: WebFlux使用非阻塞I/O来处理输入和输出,这允许应用程序在等待I/O操作完成时执行其他任务,从而提高了系统的并发性能。
- Reactive Streams: WebFlux基于Reactive Streams标准,这是一组用于异步流处理的规范。Reactive Streams定义了一套API,使得开发者可以处理异步数据流,同时考虑到背压(backpressure)控制。
- 多种运行时: WebFlux支持在不同的运行时环境中运行,包括传统的Servlet容器(如Tomcat、Jetty)以及基于Netty的运行时。
- 函数式端点: 提供了函数式端点(Functional Endpoints)的支持,允许使用函数式编程风格定义Web请求的处理。
- 支持多种响应模型: 可以使用Mono和Flux这两个响应式类型来表示单值和多值的异步结果,同时支持Java 8的CompletableFuture。
- 全面的注解支持: 提供了全面的注解支持,包括@Controller、@RequestMapping等,使得开发者可以使用熟悉的注解进行Web开发。
Spring WebFlux并不是用来替代传统的Spring MVC框架的,而是作为其补充,适用于那些需要更高性能和更好伸缩性的场景,比如处理大量的并发连接,或者需要处理实时数据流的应用程序。选择使用Spring WebFlux还是Spring MVC,取决于项目的具体需求和性能目标。
Spring Gateway与Zuul的区别
Spring Cloud Gateway和Zuul都是用于构建微服务架构中的API网关的工具,但它们有一些区别,包括设计理念、性能、灵活性等方面。
1. 基于响应式编程 vs. 传统Servlet架构:
- Spring Cloud Gateway: 基于Spring WebFlux,采用响应式编程模型,支持异步、非阻塞的处理方式。这使得Gateway能够处理大量并发请求,具备更好的性能和可伸缩性。
- Zuul: 基于传统的Servlet架构,采用阻塞I/O方式,适用于传统的同步请求处理。
2. 断言和过滤器的配置方式:
- Spring Cloud Gateway: 提供了丰富的DSL(领域特定语言)来配置路由规则,通过定义断言和过滤器来进行请求的匹配和处理。
- Zuul: 使用基于Groovy的自定义脚本来配置路由规则,这在一些情况下可能不如DSL直观。
3. 性能:
- Spring Cloud Gateway: 由于基于响应式编程模型,对于高并发的场景表现更优,能够处理大量的并发请求。
- Zuul: 在处理大量并发请求时性能可能相对较低,因为它使用的是传统的Servlet架构。
4. 适用场景:
- Spring Cloud Gateway: 适用于需要高性能和响应式编程模型的场景,特别是在云原生和微服务架构中。
- Zuul: 适用于传统的Servlet架构和较简单的应用场景,对于一些要求不那么苛刻的项目仍然是一个不错的选择。
5. 灵活性和可扩展性:
- Spring Cloud Gateway: 提供了更多的内建灵活性,支持自定义的路由断言和过滤器,易于扩展。
- Zuul: 也支持一定的扩展性,但相较之下在自定义程度上可能不如Spring Cloud Gateway。
6. 生态系统和更新维护:
- Spring Cloud Gateway: 是Spring Cloud生态系统中的一部分,与其他Spring Cloud组件更好地集成,且处于活跃的更新维护状态。
- Zuul: 原本是Netflix的项目,后来被整合到Spring Cloud中,但Netflix在宣布停止对Zuul 1的支持,转向Zuul 2(Zuul 2已更名为Zuul 1.0),因此在更新和维护上可能相对较少。
综合考虑上述因素,选择Spring Cloud Gateway还是Zuul取决于项目的具体需求和架构设计。对于要求高性能、支持响应式编程的场景,Spring Cloud Gateway可能是更好的选择;而对于一些较为传统的应用场景,Zuul仍然是一个稳定可用的API网关工具。
Spring Gateway入门案例
首先引入Gateway的Spring依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
<version>0.9.25.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
注意Gateway和web的依赖有冲突,一般不会依赖web进来
路由配置参数
spring:
application:
name: demo-spring
cloud:
gateway:
routes:
- id: demo-product
uri: http://localhost:18089
predicates:
- Path=/demo-product/**
filters:
- AddRequestHeader=X-Request-Foo, Bar #默认给过滤器设置这个头属性
- AddResponseHeader=X-Response-Foo, Baz
当启动打印这些日志就代表已经接入成功了,这些日志就是断言器里面内置很多常用的断言工具。
... : Loaded RoutePredicateFactory [After]
... : Loaded RoutePredicateFactory [Before]
... : Loaded RoutePredicateFactory [Between]
... : Loaded RoutePredicateFactory [Cookie]
... : Loaded RoutePredicateFactory [Header]
... : Loaded RoutePredicateFactory [Host]
... : Loaded RoutePredicateFactory [Method]
... : Loaded RoutePredicateFactory [Path]
... : Loaded RoutePredicateFactory [Query]
... : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
... : Loaded RoutePredicateFactory [RemoteAddr]
... : Loaded RoutePredicateFactory [Weight]
... : Loaded RoutePredicateFactory [CloudFoundryRouteService]
断言Predicate
如上Gateway提供了很多断言条件基本已经满足需求,如果有额外条件也可以自己实现。
spring:
application:
name: demo-spring
cloud:
gateway:
routes:
- id: demo-product
uri: http://localhost:18089
predicates:
- Path=/demo-product/** ##只有路径以/foo/开头的请求才会匹配该路由规则,然后被路由到
-OR- ## 还有或表达式
- Method=GET ##只有使用GET请求的请求才会匹配该路由规则。
- Header=X-Custom-Header, Bar ##只有请求头中包含X-Custom-Header: Bar的请求才会匹配该路由规则。
- Query=param=value ##只有包含查询参数param=value的请求才会匹配该路由规则。
- Host=**.example.com ##只有请求的主机名匹配**.example.com的请求才会匹配该路由规则。
- After=2018-12-25T14:33:47.789+08:00 ##这个路由规则会在东8区的2018-12-25 14:33:47前生效
- Between=2018-12-25T14:33:47.789+08:00, 2018-12-26T14:33:47.789+08:00 ##在这个区间范围生效
Spring Gateway超时配置
以下的超时配置有单独的路由超时和全局超时。超时时间的设置可能受到网关的全局配置影响。你也可以根据需要在不同的路由规则中设置不同的超时时间。超时时间的合理设置有助于控制系统的稳定性和性能。
spring:
application:
name: demo-spring
cloud:
gateway:
routes:
- id: demo-product
uri: http://localhost:18089
predicates:
- Path=/demo-product/**
filters:
##单独超时配置
- name: RequestTimeout
args:
timeout: 5000 # 超时时间,单位为毫秒
## 全局超时时间,单位为毫秒
timeout: 8000
httpclient:
connect-timeout: 5000 # 连接超时时间,单位为毫秒
response-timeout: 10000 # 响应超时时间,单位为毫秒
Spring Gateway过滤器
Spring Cloud Gateway 的 Filter 从作用范围可分为另外两种 GatewayFilter(局部)与 GlobalFilter(全局)。
1、GatewayFilter :应用到单个路由或者一个分组的路由上。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
@Component
public class MyCustomFilter extends AbstractGatewayFilterFactory<MyCustomFilter.Config> {
public MyCustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// 在这里定义过滤器的逻辑
return (exchange, chain) -> {
// Your logic here
return chain.filter(exchange);
};
}
public static class Config {
// 配置参数,如果有的话
}
}
配置
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- MyCustomFilter= # 使用过滤器的默认配置
# 或者
# - name: MyCustomFilter
# args:
# key: value # 配置过滤器的参数
2、GlobalFilter :应用到所有的路由上。
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class MyCustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 在请求被路由到目标地址之前的逻辑
System.out.println("Pre Global Filter Logic");
// 继续执行过滤器链
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 在请求被路由到目标地址之后的逻辑
System.out.println("Post Global Filter Logic");
}));
}
@Override
public int getOrder() {
// 指定过滤器的执行顺序,数字越小越先执行
return Ordered.LOWEST_PRECEDENCE;
}
}
全局过滤器无需额外配置
Spring Gateway工作流程
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Filter在**“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控**等有着非常重要的作用。
在整个的处理过程中,有一个重要的点就是请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。
总结
Spring Cloud Gateway提供了一个强大而灵活的API网关解决方案,能够帮助开发者简化微服务架构中的服务调用、路由和过滤等任务,提供了丰富的功能和易于扩展的机制。