Spring Cloud Gateway 源码剖析:请求过滤、限流熔断与动态路由配置
各位朋友,大家好!今天我们来深入探讨 Spring Cloud Gateway 的源码,重点分析其核心功能:请求过滤、限流熔断以及动态路由配置。Spring Cloud Gateway 作为 Spring Cloud 生态系统中重要的网关组件,在微服务架构中扮演着至关重要的角色,理解其内部机制对于构建稳定、高效的微服务系统至关重要。
一、Spring Cloud Gateway 架构概览
在深入源码之前,我们先对 Spring Cloud Gateway 的整体架构有个大致的了解。Spring Cloud Gateway 基于 Spring WebFlux 构建,采用 Reactor 响应式编程模型,具有高性能、非阻塞的特点。
核心组件:
- Gateway Handler Mapping: 负责将请求映射到对应的 RoutePredicateHandlerMapping。
- RoutePredicateHandlerMapping: 匹配请求路由,并根据匹配结果选择对应的 GatewayFilter。
- GatewayFilter: 执行具体的过滤逻辑,例如修改请求头、鉴权、限流等。
- Route: 路由定义,包含 Predicate 和 Filter 列表。
- Predicate: 断言,用于匹配请求,决定是否应用该路由。
- GatewayFilterChain: 过滤器链,负责执行一系列 GatewayFilter。
- WebClient: 用于向后端服务发起请求。
请求处理流程:
- 客户端发起请求。
- Gateway Handler Mapping 接收到请求,并将其传递给 RoutePredicateHandlerMapping。
- RoutePredicateHandlerMapping 根据配置的 Predicate 匹配路由。
- 如果匹配成功,则获取该路由对应的 GatewayFilter 列表,构建 GatewayFilterChain。
- GatewayFilterChain 依次执行 Filter 链中的每个 GatewayFilter。
- 最后一个 Filter 通常是
RouteToRequestUrlFilter
,它会将请求转发到后端服务。 - 后端服务处理请求并返回响应。
- 响应经过 GatewayFilterChain 逆向传递,可以进行一些后置处理。
- 最终将响应返回给客户端。
二、请求过滤源码分析
请求过滤是 Spring Cloud Gateway 最基本的功能之一。它允许我们对请求进行各种处理,例如添加请求头、修改请求体、鉴权等。
核心接口:GatewayFilter
GatewayFilter
是所有过滤器的核心接口,定义了 filter
方法,该方法接收 ServerWebExchange
和 GatewayFilterChain
作为参数。
public interface GatewayFilter extends ShortcutConfigurable {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
// ...省略其他方法
}
ServerWebExchange
:封装了 HTTP 请求和响应的上下文信息。GatewayFilterChain
:过滤器链,负责调用下一个过滤器。
自定义 GatewayFilter
要实现自定义的 GatewayFilter,我们需要实现 GatewayFilter
接口。例如,我们可以创建一个简单的过滤器,用于添加请求头:
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class AddRequestHeaderGatewayFilter implements GatewayFilter {
private final String headerName;
private final String headerValue;
public AddRequestHeaderGatewayFilter(String headerName, String headerValue) {
this.headerName = headerName;
this.headerValue = headerValue;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest().mutate()
.header(headerName, headerValue)
.build();
ServerWebExchange mutatedExchange = exchange.mutate()
.request(request)
.build();
return chain.filter(mutatedExchange);
}
}
在这个例子中,我们创建了一个 AddRequestHeaderGatewayFilter
,它接收 headerName
和 headerValue
作为参数,并在请求中添加指定的请求头。
GatewayFilter
的应用
在 application.yml
或 application.properties
中,我们可以配置路由规则,并指定要应用的 GatewayFilter。
spring:
cloud:
gateway:
routes:
- id: example_route
uri: http://example.com
predicates:
- Path=/example/**
filters:
- AddRequestHeader=X-Custom-Header, CustomValue
在这个配置中,我们定义了一个名为 example_route
的路由,它将所有以 /example/**
开头的请求转发到 http://example.com
。同时,我们还指定了一个过滤器 AddRequestHeader=X-Custom-Header, CustomValue
,它会将 X-Custom-Header
请求头设置为 CustomValue
。
Spring Cloud Gateway 会自动将配置中的 AddRequestHeader
转换为 AddRequestHeaderGatewayFilter
的实例,并将其添加到过滤器链中。
源码分析:RoutePredicateHandlerMapping
RoutePredicateHandlerMapping
负责匹配请求路由,并根据匹配结果选择对应的 GatewayFilter。其核心方法是 getHandlerInternal
。
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
return lookupRoute(exchange)
.flatMap(route -> {
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, route);
return HandlerExecutionChain.just(new GatewayControllerEndpoint(route, this.compositeRouteDefinitionLocator, this.properties.getRoutes()));
}).cast(HandlerExecutionChain.class)
.flatMap(handler -> {
return applyFilters(exchange, handler);
}).switchIfEmpty(Mono.empty());
}
lookupRoute(exchange)
:根据配置的 Predicate 匹配路由。applyFilters(exchange, handler)
:将匹配到的路由对应的 GatewayFilter 列表应用到请求上。
源码分析:GatewayFilterChain
GatewayFilterChain
是过滤器链,负责执行一系列 GatewayFilter。其核心方法是 filter
。
public interface GatewayFilterChain {
/**
* Apply this filter to the current exchange and delegate to the next filter in
* the chain.
* @param exchange the current server exchange
* @return {@code Mono<Void>} to indicate when request handling is complete
*/
Mono<Void> filter(ServerWebExchange exchange);
}
DefaultGatewayFilterChain
是 GatewayFilterChain
的默认实现,它使用递归的方式依次执行 Filter 链中的每个 GatewayFilter。
三、限流熔断源码分析
限流和熔断是保证微服务系统稳定性的重要手段。Spring Cloud Gateway 提供了内置的限流和熔断机制。
限流:RequestRateLimiterGatewayFilterFactory
RequestRateLimiterGatewayFilterFactory
基于 Redis 或其他 RateLimiter 实现,用于限制单位时间内请求的数量。
核心接口:RateLimiter
RateLimiter
定义了限流器的基本接口,包括 isAllowed
方法,用于判断是否允许请求通过。
public interface RateLimiter<C> {
/**
* Configures the rate limiter given the supplied configuration.
* @param config the configuration for a rate limiter.
* @return {@link RateLimiter} that has been configured.
*/
RateLimiter<C> configure(C config);
/**
* Determines whether or not access should be allowed based on the configuration and
* current request.
* @param routeId the id of the route being accessed.
* @param exchange the current exchange.
* @return A {@link Mono} that emits a {@link Response} indicating whether or not
* access should be allowed.
*/
Mono<Response> isAllowed(String routeId, String id);
class Response {
private final boolean allowed;
private final Map<String, String> headers;
public Response(boolean allowed, Map<String, String> headers) {
this.allowed = allowed;
this.headers = headers;
}
public boolean isAllowed() {
return allowed;
}
public Map<String, String> getHeaders() {
return headers;
}
@Override
public String toString() {
return "Response{" + "allowed=" + allowed + ", headers=" + headers + '}';
}
}
}
RedisRateLimiter
Spring Cloud Gateway 默认使用 RedisRateLimiter
作为 RateLimiter 的实现。RedisRateLimiter
使用 Redis 的 Lua 脚本来实现原子性的限流操作。
配置限流
在 application.yml
中,我们可以配置路由规则,并指定要应用的限流器。
spring:
cloud:
gateway:
routes:
- id: rate_limit_route
uri: http://example.com
predicates:
- Path=/limited/**
filters:
- RequestRateLimiter=redis-rate-limiter, 10, 10
redis:
host: localhost
port: 6379
在这个配置中,我们定义了一个名为 rate_limit_route
的路由,它将所有以 /limited/**
开头的请求转发到 http://example.com
。同时,我们还指定了一个限流器 RequestRateLimiter=redis-rate-limiter, 10, 10
,它使用 redis-rate-limiter
作为 RateLimiter 的名称,允许每秒 10 个请求,令牌桶容量为 10。
熔断:HystrixGatewayFilterFactory
和 Resilience4JGatewayFilterFactory
Spring Cloud Gateway 提供了两种熔断器实现:HystrixGatewayFilterFactory
和 Resilience4JGatewayFilterFactory
。
HystrixGatewayFilterFactory
基于 Netflix Hystrix 实现,已经进入维护模式,不推荐使用。Resilience4JGatewayFilterFactory
基于 Resilience4J 实现,是更现代、更轻量级的选择。
配置熔断
在 application.yml
中,我们可以配置路由规则,并指定要应用的熔断器。
spring:
cloud:
gateway:
routes:
- id: resilience4j_route
uri: http://example.com
predicates:
- Path=/resilient/**
filters:
- name: Resilience4J
args:
name: backendA
fallbackUri: forward:/fallback
在这个配置中,我们定义了一个名为 resilience4j_route
的路由,它将所有以 /resilient/**
开头的请求转发到 http://example.com
。同时,我们还指定了一个熔断器 Resilience4J
,它的名称为 backendA
,如果后端服务不可用,则会将请求转发到 /fallback
。
源码分析:Resilience4JGatewayFilterFactory
Resilience4JGatewayFilterFactory
使用 Resilience4J 的 CircuitBreaker
和 Retry
组件来实现熔断和重试功能。
其核心逻辑在于使用 CircuitBreaker
来包装后端服务的调用,当错误率超过阈值时,CircuitBreaker
会打开,阻止后续请求,直到一段时间后尝试恢复。
四、动态路由配置源码分析
动态路由配置允许我们在运行时动态地修改路由规则,而无需重启 Spring Cloud Gateway。Spring Cloud Gateway 提供了多种动态路由配置方式,例如通过 Spring Cloud Config Server、Redis、数据库等。
核心接口:RouteDefinitionLocator
RouteDefinitionLocator
负责从不同的数据源加载路由定义。
public interface RouteDefinitionLocator {
/**
* Returns a {@link Flux} of {@link RouteDefinition} objects.
* @return a flux that emits route definitions
*/
Flux<RouteDefinition> getRouteDefinitions();
}
内置的 RouteDefinitionLocator
实现
PropertiesRouteDefinitionLocator
:从application.yml
或application.properties
文件中加载路由定义。CompositeRouteDefinitionLocator
:组合多个RouteDefinitionLocator
,允许从多个数据源加载路由定义。DiscoveryClientRouteDefinitionLocator
:从服务发现组件(例如 Eureka、Consul)中加载路由定义。
自定义 RouteDefinitionLocator
要实现自定义的 RouteDefinitionLocator
,我们需要实现 RouteDefinitionLocator
接口,并实现 getRouteDefinitions
方法。例如,我们可以创建一个 RedisRouteDefinitionLocator
,用于从 Redis 中加载路由定义。
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
@Component
public class RedisRouteDefinitionLocator implements RouteDefinitionLocator {
private final ReactiveRedisTemplate<String, RouteDefinition> redisTemplate;
public RedisRouteDefinitionLocator(ReactiveRedisTemplate<String, RouteDefinition> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return redisTemplate.keys("gateway:route:*")
.flatMap(redisTemplate.opsForValue()::get);
}
}
在这个例子中,我们创建了一个 RedisRouteDefinitionLocator
,它从 Redis 中加载所有以 gateway:route:*
开头的键对应的路由定义。
动态更新路由
要动态更新路由,我们需要使用 ApplicationEventPublisher
发布 RefreshRoutesEvent
事件。
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
public class RouteRefresher {
private final ApplicationEventPublisher publisher;
public RouteRefresher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void refreshRoutes() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
当调用 refreshRoutes
方法时,Spring Cloud Gateway 会重新加载路由定义,并更新路由表。
源码分析:CachingRouteLocator
CachingRouteLocator
是一个缓存路由定位器,它会缓存从 RouteDefinitionLocator
加载的路由定义,以提高性能。
当收到 RefreshRoutesEvent
事件时,CachingRouteLocator
会清除缓存,并重新加载路由定义。
五、核心数据结构:Route 和 RouteDefinition
Spring Cloud Gateway 中有两个重要的数据结构:Route
和 RouteDefinition
。
RouteDefinition
: 路由定义,包含路由的元数据信息,例如 ID、URI、Predicate、Filter 等。RouteDefinition
用于配置路由规则。Route
: 路由实例,是RouteDefinition
的运行时表示。Route
包含了路由的实际信息,例如匹配的 Predicate、应用的 Filter 列表等。
特性 | RouteDefinition | Route |
---|---|---|
作用 | 路由配置 | 运行时路由实例 |
包含信息 | ID, URI, Predicate 定义, Filter 定义 | ID, URI, Predicate 实例, Filter 实例 |
生命周期 | 配置时定义 | 运行时创建 |
存储位置 | 配置文件/数据库/Redis 等 | 内存中 |
RouteDefinition
通过 RouteDefinitionRouteLocator
转换为 Route
。
六、总结
我们深入分析了 Spring Cloud Gateway 的源码,重点探讨了请求过滤、限流熔断和动态路由配置的实现机制。理解这些核心概念和源码,可以帮助我们更好地使用 Spring Cloud Gateway,构建稳定、高效的微服务网关。希望今天的分享对大家有所帮助。
提炼核心,展望未来
Spring Cloud Gateway 通过灵活的过滤器链机制实现了强大的请求处理能力,利用 Redis 等技术实现了有效的限流,并借助 Resilience4J 提供了可靠的熔断机制,同时支持动态路由配置,使得网关具备高度的适应性和可扩展性。 随着云原生技术的不断发展,Spring Cloud Gateway 在微服务架构中的作用将更加重要。