Spring Cloud Gateway
是一个基于 Spring Framework
的网关解决方案,用于管理和路由微服务请求。它提供了动态路由、负载均衡、路径重写、过滤请求、限流等功能。以下是 Spring Cloud Gateway 的基本配置方法,包括路由、过滤器和限流等。
1. 基本依赖配置
在项目的 pom.xml
文件中添加 Spring Cloud Gateway
的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. 基本的路由配置
可以在 application.yml
文件中使用静态配置,也可以使用 Java 代码配置。以下是静态配置示例:
spring:
cloud:
gateway:
routes:
- id: service_route_1
uri: http://localhost:8081
predicates:
- Path=/service1/**
filters:
- RewritePath=/service1/(?<segment>.*), /$\\{segment}
- id: service_route_2
uri: lb://SERVICE-2
predicates:
- Path=/service2/**
filters:
- RemoveRequestHeader=Cookie
解析
id
: 每个路由的唯一标识。uri
: 路由目标的 URI,可以是具体 URL(如http://localhost:8081
)或服务名(如lb://SERVICE-2
)。predicates
: 路由断言,控制请求是否符合路由条件。例如Path
断言指定路径/service1/**
的请求才能通过此路由。filters
: 过滤器,可用来修改请求/响应,比如RewritePath
用来重写路径,RemoveRequestHeader
用于删除请求头。
3. 动态路由配置(Java 代码方式)
通过 RouteLocator
定义自定义路由:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/service1/**")
.filters(f -> f.rewritePath("/service1/(?<segment>.*)", "/${segment}"))
.uri("http://localhost:8081"))
.route("lb_route", r -> r.path("/service2/**")
.filters(f -> f.addRequestHeader("X-Request-Id", "my-custom-header"))
.uri("lb://SERVICE-2"))
.build();
}
}
4. 常见过滤器配置
Spring Cloud Gateway 内置了多种过滤器,以下是常用过滤器的配置方式:
-
AddRequestHeader:向请求添加一个自定义的请求头。
filters: - AddRequestHeader=X-Request-Id, 123
-
AddRequestParameter:向请求添加一个参数。
filters: - AddRequestParameter=lang, en
-
RewritePath:重写请求路径。
filters: - RewritePath=/service/(?<segment>.*), /$\\{segment}
-
StripPrefix:删除路径的前缀。
filters: - StripPrefix=1
-
Retry:重试配置,适用于调用失败后自动重试。
filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY
5. 限流配置(Rate Limiter)
使用令牌桶算法对请求进行限流,通常使用 redis-rate-limiter
。
-
引入 Redis 依赖(如果使用 Redis 作为限流器存储):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>
-
配置限流器:
spring: cloud: gateway: routes: - id: rate_limited_route uri: lb://SERVICE-3 predicates: - Path=/rate-limit/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 # 每秒产生 10 个令牌 redis-rate-limiter.burstCapacity: 20 # 最大桶容量为 20
6. 负载均衡配置
Spring Cloud Gateway
支持负载均衡,可以直接通过 lb://
指向注册在 Eureka 或 Consul 中的服务。例如:
spring:
cloud:
gateway:
routes:
- id: load_balanced_route
uri: lb://SERVICE-4
predicates:
- Path=/load-balance/**
7. 故障处理与熔断器配置(Hystrix)
可以配置熔断器来处理超时或服务不可用的情况:
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://SERVICE-5
predicates:
- Path=/circuit-breaker/**
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/fallback
8. 自定义过滤器
实现 GatewayFilter
接口来自定义过滤器,用于实现更加复杂的业务逻辑。例如,自定义日志记录、身份验证等:
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
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 CustomLoggingFilter extends AbstractGatewayFilterFactory<CustomLoggingFilter.Config> {
public static class Config {
// 配置属性可以在此定义
}
public CustomLoggingFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
System.out.println("Custom logging filter: " + request.getURI());
return chain.filter(exchange);
};
}
}
9. 全局过滤器
全局过滤器会应用于所有请求,可以实现 GlobalFilter
接口:
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("Global Filter executed for request: " + exchange.getRequest().getURI());
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1; // 设置过滤器的优先级
}
}
10. 运行监控
Spring Cloud Gateway
可以通过 Actuator
提供的 /actuator/gateway/routes
端点监控路由状态和其他信息,确保在生产环境中可以对网关配置进行有效的监控和管理。
总结
Spring Cloud Gateway 配置灵活多样,可以通过配置文件、Java 代码定义静态或动态路由,支持负载均衡、限流和熔断器等功能,满足微服务架构下的 API 网关需求。
在 Spring Cloud Gateway
的配置示例中,我们通过 routes
配置不同的路由规则,每个路由包含 id
、uri
、predicates
、filters
等配置项。这些配置项共同决定了请求如何从网关路由到目标服务。
配置项解析
spring:
cloud:
gateway:
routes:
- id: service_route_1
uri: http://localhost:8081
predicates:
- Path=/service1/**
filters:
- RewritePath=/service1/(?<segment>.*), /$\\{segment}
- id: service_route_2
uri: lb://SERVICE-2
predicates:
- Path=/service2/**
filters:
- RemoveRequestHeader=Cookie
1. id
id
: 每个路由的唯一标识,用于在系统中区分不同的路由。- 示例中的
service_route_1
和service_route_2
分别是两个不同路由的 ID。这个 ID 可以用于监控、调试,或管理特定路由规则。
2. uri
uri
: 路由的目标 URI,可以是具体的 URL,也可以是服务名称。http://localhost:8081
:直接指定目标服务的地址。请求符合路由规则时会被转发到localhost:8081
上的服务。lb://SERVICE-2
:表示使用Spring Cloud
的负载均衡机制,将请求转发到服务注册中心中名称为SERVICE-2
的服务实例上。
注意:当 uri
以 lb://
为前缀时,表示使用负载均衡,适合动态获取多个实例。
3. predicates
predicates
: 路由断言,用于判断请求是否符合此路由规则。符合条件的请求会被转发到对应的 URI。Path=/service1/**
:这是Path
断言,用于匹配请求路径。如果请求路径匹配/service1/**
(如/service1/order/123
),则符合此路由条件。/service1/**
表示/service1/
后面可以跟任意路径。Path=/service2/**
:同样是Path
断言,用于匹配路径/service2/**
的请求。
在 Spring Cloud Gateway
中,断言类型丰富,包括 Path
、Method
、Header
等,具体的组合可以实现复杂的路由需求。
4. filters
filters
: 路由过滤器,用于在请求进入目标服务之前或响应返回客户端之前,修改请求或响应的内容。过滤器可以重写路径、移除请求头、添加请求参数等操作。
RewritePath
- 作用:
RewritePath
用于对路径进行重写。 - 格式:
RewritePath=/<oldPath>/regex, /<newPath>/replacement
- 示例:
RewritePath=/service1/(?<segment>.*), /$\\{segment}
service1/(?<segment>.*)
:匹配请求路径中的/service1/
后面部分,并将匹配部分命名为segment
。/$\\{segment}
:将segment
中的内容替换到新路径中,从而实现路径的重写。- 效果:请求路径
/service1/order/123
将被重写为/order/123
,即去掉了/service1
前缀。
RemoveRequestHeader
- 作用:
RemoveRequestHeader
用于删除指定的请求头。 - 格式:
RemoveRequestHeader=<headerName>
- 示例:
RemoveRequestHeader=Cookie
- 表示从请求中移除
Cookie
请求头,通常用于避免将敏感信息传递到后端服务,或在负载均衡场景下减少无关请求头。 - 效果:当请求符合
service_route_2
路由条件时,会移除Cookie
头,确保目标服务SERVICE-2
不会收到客户端的 Cookie 信息。
- 表示从请求中移除
配置示例总结
service_route_1
:将请求路径匹配为/service1/**
的请求重写为去掉前缀/service1
的路径,再转发到localhost:8081
。service_route_2
:将路径为/service2/**
的请求移除Cookie
请求头后,通过负载均衡方式转发到SERVICE-2
服务。
示例请求匹配流程
-
匹配
service_route_1
路由:- 假设请求路径为
/service1/order/123
。 - 断言
Path=/service1/**
生效,符合此路由。 RewritePath
过滤器生效,将路径重写为/order/123
。- 请求被转发到
http://localhost:8081/order/123
。
- 假设请求路径为
-
匹配
service_route_2
路由:- 假设请求路径为
/service2/customer/456
,并且包含Cookie
请求头。 - 断言
Path=/service2/**
生效,符合此路由。 RemoveRequestHeader=Cookie
过滤器生效,将Cookie
请求头移除。- 请求被转发到
SERVICE-2
服务中的某个实例,路径为/customer/456
。
- 假设请求路径为
小结
Spring Cloud Gateway
中的每个路由都由id
唯一标识。uri
指定目标服务的地址,可以是静态的 URL 或通过lb://
表示的负载均衡地址。predicates
指定请求条件,只有符合的请求才会进入此路由。filters
可以对符合路由条件的请求或响应进行处理,例如路径重写、删除请求头等。