Spring Cloud Gateway 是 Spring Cloud 微服务架构中的一个重要组件,用于提供 API 网关功能。作为 API 网关,Spring Cloud Gateway 充当客户端和后端服务之间的代理,负责请求路由、过滤、安全认证、负载均衡等功能。在分布式系统中,网关是非常关键的,它可以统一管理所有服务的入口,简化客户端调用,增强系统的安全性和稳定性。
1. Spring Cloud Gateway 的作用
Spring Cloud Gateway 是基于 Spring 5、Spring Boot 2 和 Spring WebFlux 构建的,它提供了一种简单而高效的方式来实现 API 网关功能。Spring Cloud Gateway 的主要功能包括:
- 路由:根据请求的 URL、请求头或其他条件将请求路由到后端服务。
- 过滤:提供请求和响应的前置和后置过滤器,能够进行认证、限流、日志记录等操作。
- 负载均衡:可以与 Spring Cloud LoadBalancer 结合使用,支持负载均衡功能。
- 安全性:支持与 OAuth 2.0、JWT 以及其他安全框架的集成,确保请求的安全。
2. Spring Cloud Gateway 项目搭建
2.1 引入依赖
首先,在 Spring Boot 项目中引入 Spring Cloud Gateway 的依赖:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
如果项目中已经使用了 Spring Cloud 组件,需要添加 Spring Cloud 的版本依赖管理:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.2 基本配置
在 application.yml
中,我们可以配置 Spring Cloud Gateway 的路由规则。以下是一个简单的路由配置示例:
yaml
spring:
cloud:
gateway:
routes:
- id: service-route
uri: http://localhost:8081
predicates:
- Path=/api/service/**
filters:
- StripPrefix=2
在这个配置中:
id
是路由的唯一标识。uri
是请求被路由到的目标服务地址。predicates
是路由匹配条件,在这里使用的是Path
谓词,将/api/service/**
路径的请求路由到指定服务。filters
是过滤器配置,在这里StripPrefix=2
表示去除请求路径中的前两部分路径,如/api/service/xxx
变为/xxx
。
3. 路由与谓词
Spring Cloud Gateway 的路由由 谓词 和 过滤器 构成。谓词决定请求是否符合路由条件,过滤器则用于处理请求或响应。
3.1 常用谓词
Spring Cloud Gateway 提供了多种谓词(Predicates),用于定义路由规则。例如:
- Path:根据请求的路径匹配。
- Host:根据请求的 Host 匹配。
- Method:根据 HTTP 请求方法匹配,如 GET、POST。
- Header:根据请求头匹配。
- Query:根据请求参数匹配。
以下是一个路由配置示例,展示了常用的谓词:
yaml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user/**
- Method=GET
filters:
- AddRequestHeader=X-Request-User, User
在这个示例中,所有以 /user/**
开头的 GET 请求会被路由到 USER-SERVICE
,并添加一个请求头 X-Request-User
。
3.2 自定义谓词
除了内置的谓词,Spring Cloud Gateway 还允许自定义谓词。可以通过实现 RoutePredicateFactory
来实现自定义谓词。例如,下面实现了一个自定义谓词,匹配客户端 IP 地址:
java
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
public class IpCheckRoutePredicateFactory extends AbstractRoutePredicateFactory<IpCheckRoutePredicateFactory.Config> {
public IpCheckRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
String clientIp = exchange.getRequest().getRemoteAddress().getHostString();
return config.allowedIps.contains(clientIp);
};
}
public static class Config {
private List<String> allowedIps;
// Getters and Setters
}
}
在配置文件中使用自定义谓词:
yaml
spring:
cloud:
gateway:
routes:
- id: ip-filter-route
uri: http://localhost:8081
predicates:
- Path=/admin/**
- IpCheck=192.168.1.1, 192.168.1.2
4. 过滤器
过滤器(Filters)用于在请求和响应的过程中对数据进行处理。Spring Cloud Gateway 提供了两种类型的过滤器:
- 全局过滤器:应用于所有路由。
- 路由过滤器:只应用于特定路由。
4.1 常用过滤器
一些常用的路由过滤器包括:
- AddRequestHeader:为请求添加请求头。
- StripPrefix:移除请求路径中的前缀。
- AddResponseHeader:为响应添加响应头。
- RequestRateLimiter:限流。
例如,以下配置为请求添加一个自定义请求头:
yaml
spring:
cloud:
gateway:
routes:
- id: add-header-route
uri: http://localhost:8081
predicates:
- Path=/api/addheader/**
filters:
- AddRequestHeader=X-Custom-Header, Value
4.2 限流过滤器
Spring Cloud Gateway 提供了基于 Redis 的限流过滤器 RequestRateLimiter
,用于限制某个路由的请求速率。
首先,需要在项目中引入 spring-boot-starter-data-redis
依赖,以支持 Redis:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
然后,在配置文件中添加限流规则:
yaml
spring:
cloud:
gateway:
routes:
- id: rate-limiter-route
uri: http://localhost:8081
predicates:
- Path=/api/ratelimit/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒补充令牌数
redis-rate-limiter.burstCapacity: 20 # 最大令牌桶容量
key-resolver: '#{@ipKeyResolver}'
这里使用了 RequestRateLimiter
过滤器,并定义了每秒允许 10 个请求,最大令牌桶容量为 20。
还需要定义一个 IP 地址作为限流依据的 KeyResolver
:
java
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class RateLimiterConfig {
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
}
}
5. 集成 Spring Cloud Eureka 和负载均衡
Spring Cloud Gateway 可以无缝集成 Spring Cloud Eureka 来实现服务发现和负载均衡。要启用服务发现和负载均衡,首先需要引入相关依赖:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
在 application.yml
中,配置 Eureka 客户端并启用负载均衡:
yaml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
preferIpAddress: true
spring:
cloud:
gateway:
routes:
- id: lb-route
uri: lb://USER-SERVICE
predicates:
- Path=/user/**
在这个示例中,我们将请求路由到 Eureka 注册的 USER-SERVICE
,并通过 Spring Cloud LoadBalancer 实现负载均衡。
6. 总
结
Spring Cloud Gateway 是一个功能强大、扩展性强的 API 网关解决方案,特别适合在 Spring Cloud 微服务架构中使用。通过 Spring Cloud Gateway,可以轻松实现路由、过滤、负载均衡、限流等功能,为分布式系统提供可靠的服务网关。本文详细介绍了 Spring Cloud Gateway 的路由、谓词、过滤器及限流等功能,并展示了如何集成 Spring Cloud Eureka 和 Redis,构建一个完整的网关服务。