Appearance
路由谓词工厂
Spring Cloud Gateway 作为微服务架构中的 API 网关,通过路由谓词工厂(Route Predicate Factory)来决定请求应该被路由到哪个服务。谓词工厂就像是网关的"路由规则引擎",它会检查 HTTP 请求的各种属性,然后决定是否匹配特定的路由。
什么是路由谓词工厂?
路由谓词工厂是 Spring Cloud Gateway 中用于匹配 HTTP 请求的组件。它基于 Spring WebFlux 的HandlerMapping基础设施工作,每个谓词工厂都会检查 HTTP 请求的不同属性(如时间、路径、请求头等),并返回匹配结果。多个谓词工厂可以通过逻辑AND操作组合使用。
INFO
- After、Before、Between:基于时间的谓词工厂
- Cookie、Header、Host、Method、Path、Query:基于 HTTP 请求属性的谓词工厂
- RemoteAddr、XForwardedRemoteAddr:基于网络地址的谓词工厂
- Weight:基于权重的谓词工厂,用于流量分配
- 组合谓词:可以将多个谓词工厂组合使用,实现复杂的路由逻辑
路由谓词工厂解决了微服务架构中请求路由的核心问题:如何根据请求特征智能地将请求转发到合适的后端服务。
1. 时间相关谓词工厂
After 谓词工厂
After谓词工厂用于匹配指定时间之后的请求,常用于定时发布功能和灰度发布场景。
业务场景:新功能需要在特定时间点(如 2024 年 12 月 1 日)才对外开放。
kotlin
@Configuration
class GatewayConfig {
@Bean
fun customRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("new_feature_route") { r ->
r.after(ZonedDateTime.of(2024, 12, 1, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai")))
.uri("https://new-feature-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: new_feature_route
uri: https://new-feature-service.com
predicates:
- After=2024-12-01T00:00:00.000+08:00[Asia/Shanghai]Before 谓词工厂
Before谓词工厂匹配指定时间之前的请求,适用于限时活动和系统维护场景。
业务场景:双十一活动只在 11 月 11 日 24 点前有效。
kotlin
@Configuration
class GatewayConfig {
@Bean
fun doubleElevenRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("double_eleven_route") { r ->
r.before(ZonedDateTime.of(2024, 11, 12, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai")))
.uri("https://promotion-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: double_eleven_route
uri: https://promotion-service.com
predicates:
- Before=2024-11-12T00:00:00.000+08:00[Asia/Shanghai]Between 谓词工厂
Between谓词工厂匹配两个时间点之间的请求,完美适用于限时活动、维护窗口等场景。
业务场景:系统维护窗口,只有在维护时间段内才路由到维护页面。
kotlin
@Configuration
class GatewayConfig {
@Bean
fun maintenanceRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("maintenance_route") { r ->
r.between(
ZonedDateTime.of(2024, 6, 15, 2, 0, 0, 0, ZoneId.of("Asia/Shanghai")),
ZonedDateTime.of(2024, 6, 15, 6, 0, 0, 0, ZoneId.of("Asia/Shanghai"))
)
.uri("https://maintenance-page.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: maintenance_route
uri: https://maintenance-page.com
predicates:
- Between=2024-06-15T02:00:00.000+08:00[Asia/Shanghai], 2024-06-15T06:00:00.000+08:00[Asia/Shanghai]TIP
时间相关的谓词工厂常用于实现定时发布、灰度发布、限时活动等业务场景。使用时注意时区设置,避免因时区问题导致的路由错误。
2. HTTP 请求属性谓词工厂
Cookie 谓词工厂
Cookie谓词工厂根据 Cookie 的名称和值(支持正则表达式)进行匹配,常用于用户身份验证和个性化路由。
业务场景:VIP 用户通过特定 Cookie 路由到专用服务,获得更好的服务质量。
kotlin
@Component
class VipUserRoute {
@Bean
fun vipUserRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("vip_user_route") { r ->
r.cookie("user_type", "vip.*") // 匹配vip开头的用户类型
.uri("https://vip-service.com")
}
.route("normal_user_route") { r ->
r.cookie("user_type", "normal")
.uri("https://normal-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: vip_user_route
uri: https://vip-service.com
predicates:
- Cookie=user_type, vip.*
- id: normal_user_route
uri: https://normal-service.com
predicates:
- Cookie=user_type, normalHeader 谓词工厂
Header谓词工厂根据 HTTP 请求头进行匹配,常用于API 版本控制、设备类型路由等场景。
业务场景:根据客户端类型(移动端、Web 端)路由到不同的服务。
kotlin
@Component
class ClientTypeRoute {
@Bean
fun clientTypeRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("mobile_api_route") { r ->
r.header("X-Client-Type", "mobile")
.uri("https://mobile-api.com")
}
.route("web_api_route") { r ->
r.header("X-Client-Type", "web")
.uri("https://web-api.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: mobile_api_route
uri: https://mobile-api.com
predicates:
- Header=X-Client-Type, mobile
- id: web_api_route
uri: https://web-api.com
predicates:
- Header=X-Client-Type, webAPI 版本控制示例
kotlin
@Component
class ApiVersionRoute {
@Bean
fun apiVersionRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("api_v1_route") { r ->
r.header("X-API-Version", "v1")
.uri("https://api-v1.com")
}
.route("api_v2_route") { r ->
r.header("X-API-Version", "v2")
.uri("https://api-v2.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: api_v1_route
uri: https://api-v1.com
predicates:
- Header=X-API-Version, v1
- id: api_v2_route
uri: https://api-v2.com
predicates:
- Header=X-API-Version, v2Host 谓词工厂
Host谓词工厂根据 Host 请求头进行匹配,支持 Ant 风格的模式匹配,常用于多租户系统、环境隔离。
业务场景:多租户 SaaS 系统,不同租户使用不同子域名访问各自的服务实例。
Host 谓词工厂提取的 URI 模板变量(如{tenantId})会被存储在ServerWebExchange.getAttributes()中,可以在后续的过滤器中使用。
kotlin
@Component
class MultiTenantRoute {
@Bean
fun tenantRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("tenant_a_route") { r ->
r.host("*.tenant-a.example.com")
.uri("https://tenant-a-service.com")
}
.route("tenant_b_route") { r ->
r.host("*.tenant-b.example.com")
.uri("https://tenant-b-service.com")
}
.route("tenant_pattern_route") { r ->
r.host("**.tenant-{tenantId}.example.com")
.uri("https://tenant-service.com")
}
.route("default_tenant_route") { r ->
r.host("**.example.com")
.uri("https://default-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: tenant_a_route
uri: https://tenant-a-service.com
predicates:
- Host=*.tenant-a.example.com
- id: tenant_b_route
uri: https://tenant-b-service.com
predicates:
- Host=*.tenant-b.example.com
- id: tenant_pattern_route
uri: https://tenant-service.com
predicates:
- Host=**.tenant-{tenantId}.example.com
- id: default_tenant_route
uri: https://default-service.com
predicates:
- Host=**.example.comMethod 谓词工厂
Method谓词工厂根据 HTTP 方法进行匹配,常用于RESTful API 路由、读写分离等场景。
读写分离架构,GET 请求路由到只读服务,POST/PUT/DELETE 路由到读写服务。
kotlin
@Component
class ReadWriteSeparationRoute {
@Bean
fun readWriteRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("read_only_route") { r ->
r.method(HttpMethod.GET)
.uri("https://read-only-service.com")
}
.route("read_write_route") { r ->
r.method(HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)
.uri("https://read-write-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: read_only_route
uri: https://read-only-service.com
predicates:
- Method=GET
- id: read_write_route
uri: https://read-write-service.com
predicates:
- Method=POST,PUT,DELETEPath 谓词工厂
Path谓词工厂是最常用的谓词工厂之一,根据请求路径进行匹配,支持 Spring 的PathMatcher模式。
业务场景:微服务架构中根据 API 路径路由到不同的服务。
kotlin
@Component
class MicroserviceRoute {
@Bean
fun microserviceRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("user_service_route") { r ->
r.path("/api/users/**")
.uri("https://user-service.com")
}
.route("order_service_route") { r ->
r.path("/api/orders/**")
.uri("https://order-service.com")
}
.route("product_service_route") { r ->
r.path("/api/products/**")
.uri("https://product-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: user_service_route
uri: https://user-service.com
predicates:
- Path=/api/users/**
- id: order_service_route
uri: https://order-service.com
predicates:
- Path=/api/orders/**
- id: product_service_route
uri: https://product-service.com
predicates:
- Path=/api/products/**路径变量提取示例
业务场景:提取路径中的变量
kotlin
@Component
class PathVariableExtraction {
@Bean
fun pathVariableRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("user_detail_route") { r ->
r.path("/api/users/{userId}")
.uri("https://user-service.com")
}
.route("order_detail_route") { r ->
r.path("/api/orders/{orderId}/items/{itemId}")
.uri("https://order-service.com")
}
.build()
}
// 在过滤器中获取路径变量
@Bean
fun pathVariableFilter(): GatewayFilter {
return GatewayFilter { exchange, chain ->
val uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange)
val userId = uriVariables["userId"]
val orderId = uriVariables["orderId"]
// 可以将路径变量添加到请求头中传递给下游服务
if (userId != null) {
exchange.request.mutate()
.header("X-User-Id", userId)
.build()
}
chain.filter(exchange)
}
}
}yaml
spring:
cloud:
gateway:
routes:
- id: user_detail_route
uri: https://user-service.com
predicates:
- Path=/api/users/{userId}
- id: order_detail_route
uri: https://order-service.com
predicates:
- Path=/api/orders/{orderId}/items/{itemId}WARNING
当设置了spring.webflux.base-path属性时,该值会自动添加到路径模式前缀。例如,spring.webflux.base-path=/app和路径模式/red/{segment},实际匹配的完整模式为/app/red/{segment}。
Query 谓词工厂
Query谓词工厂根据查询参数进行匹配,常用于功能开关、A/B 测试等场景。
业务场景:A/B 测试,根据查询参数决定使用新版本还是旧版本的服务。
kotlin
@Component
class FeatureFlagRoute {
@Bean
fun featureFlagRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("feature_flag_new") { r ->
r.query("version", "new")
.uri("https://new-feature-service.com")
}
.route("feature_flag_beta") { r ->
r.query("beta", "true")
.uri("https://beta-service.com")
}
.route("default_service") { r ->
r.query("version") // 只要存在version参数
.uri("https://default-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: feature_flag_new
uri: https://new-feature-service.com
predicates:
- Query=version, new
- id: feature_flag_beta
uri: https://beta-service.com
predicates:
- Query=beta, true
- id: default_service
uri: https://default-service.com
predicates:
- Query=version3. 网络相关谓词工厂
RemoteAddr 谓词工厂
RemoteAddr谓词工厂根据客户端 IP 地址进行匹配,支持 CIDR 表示法,常用于地理位置路由、安全控制等场景。
业务场景:内网管理请求路由到管理服务,外网请求路由到公开服务。
kotlin
@Component
class NetworkAccessRoute {
@Bean
fun networkAccessRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("internal_admin_route") { r ->
r.remoteAddr("192.168.1.0/24", "10.0.0.0/8")
.uri("https://admin-service.com")
}
.route("public_service_route") { r ->
r.remoteAddr("0.0.0.0/0")
.uri("https://public-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: internal_admin_route
uri: https://admin-service.com
predicates:
- RemoteAddr=192.168.1.0/24,10.0.0.0/8
- id: public_service_route
uri: https://public-service.com
predicates:
- RemoteAddr=0.0.0.0/0高级配置:处理代理环境
在生产环境中,Gateway 通常部署在负载均衡器或反向代理后面,需要正确解析真实客户端 IP:
kotlin
@Configuration
class RemoteAddrConfig {
@Bean
fun remoteAddrRoutes(builder: RouteLocatorBuilder): RouteLocator {
// 信任一层代理的配置
val resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1)
return builder.routes()
.route("trusted_proxy_route") { r ->
r.remoteAddr(resolver, "10.1.1.0/24")
.uri("https://internal-service.com")
}
.route("direct_access_route") { r ->
r.remoteAddr("192.168.1.0/24")
.uri("https://direct-service.com")
}
.build()
}
}yaml
# 对于代理环境,需要在代码中配置RemoteAddressResolver
# YAML配置仅适用于直接IP匹配场景
spring:
cloud:
gateway:
routes:
- id: direct_access_route
uri: https://direct-service.com
predicates:
- RemoteAddr=192.168.1.0/24XForwarded Remote Addr 谓词工厂
专门处理X-Forwarded-For请求头的谓词工厂,适用于代理环境下的 IP 匹配。
业务场景:CDN 加速场景下,需要根据真实用户 IP 进行地理位置路由。
kotlin
@Component
class XForwardedRemoteAddrRoute {
@Bean
fun xForwardedRemoteAddrRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("china_users_route") { r ->
r.xForwardedRemoteAddr("114.114.114.0/24", "223.5.5.0/24")
.uri("https://china-service.com")
}
.route("global_users_route") { r ->
r.xForwardedRemoteAddr("0.0.0.0/0")
.uri("https://global-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: china_users_route
uri: https://china-service.com
predicates:
- XForwardedRemoteAddr=114.114.114.0/24,223.5.5.0/24
- id: global_users_route
uri: https://global-service.com
predicates:
- XForwardedRemoteAddr=0.0.0.0/04. 负载均衡相关谓词工厂
Weight 谓词工厂
Weight谓词工厂根据权重进行流量分配,常用于金丝雀发布、蓝绿部署、灰度发布等场景。
新版本灰度发布,10%流量路由到新版本,90%流量保持在稳定版本。
kotlin
@Component
class CanaryDeploymentRoute {
@Bean
fun canaryDeploymentRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("stable_version") { r ->
r.weight("version_group", 90)
.uri("https://stable-service.com")
}
.route("canary_version") { r ->
r.weight("version_group", 10)
.uri("https://canary-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
- id: stable_version
uri: https://stable-service.com
predicates:
- Weight=version_group, 90
- id: canary_version
uri: https://canary-service.com
predicates:
- Weight=version_group, 10更复杂的灰度发布策略
业务场景:运行时动态调整权重的功能
kotlin
@Configuration
@ConfigurationProperties(prefix = "canary.deployment")
class AdvancedCanaryDeployment {
var stableWeight: Int = 90
var canaryWeight: Int = 10
var betaWeight: Int = 0
@Bean
fun canaryRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("stable_service") { r ->
r.weight("deployment_group", stableWeight)
.uri("https://stable-service.com")
}
.route("canary_service") { r ->
r.weight("deployment_group", canaryWeight)
.uri("https://canary-service.com")
}
.route("beta_service") { r ->
r.weight("deployment_group", betaWeight)
.uri("https://beta-service.com")
}
.build()
}
// 运行时动态调整权重的功能
@EventListener
fun handleWeightChange(event: WeightChangeEvent) {
// 实现动态权重调整逻辑
when (event.targetVersion) {
"canary" -> {
canaryWeight = event.newWeight
stableWeight = 100 - canaryWeight - betaWeight
}
"beta" -> {
betaWeight = event.newWeight
stableWeight = 100 - canaryWeight - betaWeight
}
}
}
}
data class WeightChangeEvent(
val targetVersion: String,
val newWeight: Int
)yaml
canary:
deployment:
stable-weight: 90
canary-weight: 10
beta-weight: 0
spring:
cloud:
gateway:
routes:
- id: stable_service
uri: https://stable-service.com
predicates:
- Weight=deployment_group, ${canary.deployment.stable-weight}
- id: canary_service
uri: https://canary-service.com
predicates:
- Weight=deployment_group, ${canary.deployment.canary-weight}
- id: beta_service
uri: https://beta-service.com
predicates:
- Weight=deployment_group, ${canary.deployment.beta-weight}5. 组合谓词的高级用法
业务场景:组合多个谓词来实现复杂的路由逻辑
kotlin
@Configuration
class ComplexRouting {
@Bean
fun complexRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
// VIP用户的移动端API v2版本
.route("vip_mobile_api_v2") { r ->
r.cookie("user_type", "vip")
.and()
.header("X-Client-Type", "mobile")
.and()
.header("X-API-Version", "v2")
.and()
.path("/api/**")
.uri("https://vip-mobile-api-v2.com")
}
// 工作时间的管理接口(内网访问)
.route("admin_working_hours") { r ->
r.remoteAddr("192.168.1.0/24")
.and()
.between(
ZonedDateTime.now().with(LocalTime.of(9, 0)),
ZonedDateTime.now().with(LocalTime.of(18, 0))
)
.and()
.path("/admin/**")
.uri("https://admin-service.com")
}
// 限时活动的特殊路由
.route("special_promotion") { r ->
r.between(
ZonedDateTime.of(2024, 11, 11, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai")),
ZonedDateTime.of(2024, 11, 12, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai"))
)
.and()
.query("promotion", "double11")
.and()
.method(HttpMethod.GET, HttpMethod.POST)
.uri("https://promotion-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
# VIP用户的移动端API v2版本
- id: vip_mobile_api_v2
uri: https://vip-mobile-api-v2.com
predicates:
- Cookie=user_type, vip
- Header=X-Client-Type, mobile
- Header=X-API-Version, v2
- Path=/api/**
# 限时活动的特殊路由
- id: special_promotion
uri: https://promotion-service.com
predicates:
- Between=2024-11-11T00:00:00.000+08:00[Asia/Shanghai], 2024-11-12T00:00:00.000+08:00[Asia/Shanghai]
- Query=promotion, double11
- Method=GET,POST6. 实际业务场景案例
电商系统的路由策略
配置示例
kotlin
@Configuration
class ECommerceGateway {
@Bean
fun ecommerceRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
// VIP用户路由到高性能服务
.route("vip_user_service") { r ->
r.cookie("membership", "vip|premium")
.and()
.path("/api/products/**", "/api/orders/**")
.uri("https://vip-service.com")
}
// 移动端用户路由到移动优化服务
.route("mobile_optimized_service") { r ->
r.header("User-Agent", ".*Mobile.*")
.and()
.path("/api/**")
.uri("https://mobile-service.com")
}
// 促销时段的特殊路由
.route("promotion_service") { r ->
r.between(
ZonedDateTime.now().withHour(10),
ZonedDateTime.now().withHour(22)
)
.and()
.path("/api/promotions/**")
.uri("https://promotion-service.com")
}
// 管理员后台(仅内网访问)
.route("admin_service") { r ->
r.remoteAddr("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")
.and()
.path("/admin/**")
.uri("https://admin-service.com")
}
// 默认服务
.route("default_service") { r ->
r.path("/**")
.uri("https://default-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
# VIP用户路由到高性能服务
- id: vip_user_service
uri: https://vip-service.com
predicates:
- Cookie=membership, vip|premium
- Path=/api/products/**,/api/orders/**
# 移动端用户路由到移动优化服务
- id: mobile_optimized_service
uri: https://mobile-service.com
predicates:
- Header=User-Agent, .*Mobile.*
- Path=/api/**
# 管理员后台(仅内网访问)
- id: admin_service
uri: https://admin-service.com
predicates:
- RemoteAddr=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
- Path=/admin/**
# 默认服务
- id: default_service
uri: https://default-service.com
predicates:
- Path=/**7. 最佳实践和注意事项
性能优化建议
TIP
路由顺序很重要:Spring Cloud Gateway 按照路由定义的顺序进行匹配,应将更具体的路由放在前面,通用路由放在后面。
优化路由顺序示例
kotlin
@Configuration
class OptimizedRouting {
@Bean
fun optimizedRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
// 具体路由放在前面
.route("specific_api_v2") { r ->
r.path("/api/v2/users/{userId}/orders")
.and()
.method(HttpMethod.GET)
.uri("https://user-order-service.com")
}
// 较具体的路由
.route("api_v2_users") { r ->
r.path("/api/v2/users/**")
.uri("https://user-service-v2.com")
}
// 较通用的路由
.route("api_v2") { r ->
r.path("/api/v2/**")
.uri("https://api-v2-gateway.com")
}
// 最通用的路由放在最后
.route("fallback") { r ->
r.path("/**")
.uri("https://default-service.com")
}
.build()
}
}yaml
spring:
cloud:
gateway:
routes:
# 具体路由放在前面
- id: specific_api_v2
uri: https://user-order-service.com
predicates:
- Path=/api/v2/users/{userId}/orders
- Method=GET
# 较具体的路由
- id: api_v2_users
uri: https://user-service-v2.com
predicates:
- Path=/api/v2/users/**
# 较通用的路由
- id: api_v2
uri: https://api-v2-gateway.com
predicates:
- Path=/api/v2/**
# 最通用的路由放在最后
- id: fallback
uri: https://default-service.com
predicates:
- Path=/**调试和监控
在生产环境中,建议启用路由的调试日志和监控指标,以便及时发现和解决路由问题。
yaml
logging:
level:
org.springframework.cloud.gateway: DEBUG
org.springframework.web.reactive.function.client: DEBUG
management:
endpoints:
web:
exposure:
include: health, metrics, gateway
endpoint:
gateway:
enabled: true常见陷阱和解决方案
WARNING
时区问题:使用时间相关谓词时,务必明确指定时区,避免因服务器时区不同导致的路由错误。
CAUTION
正则表达式性能:Cookie 和 Header 谓词工厂中的正则表达式会影响性能,应该使用简单、高效的正则表达式。
kotlin
// ❌ 避免复杂的正则表达式
.cookie("session", "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{32}$")
// ✅ 使用简单的模式匹配
.cookie("session", "sess_.*")动态路由配置
对于需要动态修改路由的场景,可以结合配置中心实现:
动态路由配置示例
kotlin
@Component
@RefreshScope
class DynamicRouting {
// 使用配置中心动态加载路由权重
@Value("\${gateway.routes.user.weight:80}")
private var userServiceWeight: Int = 80
@Value("\${gateway.routes.user-v2.weight:20}")
private var userServiceV2Weight: Int = 20
@Bean
@RefreshScope
fun dynamicRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("user_service_v1") { r ->
r.weight("user_service_group", userServiceWeight)
.and()
.path("/api/users/**")
.uri("https://user-service-v1.com")
}
.route("user_service_v2") { r ->
r.weight("user_service_group", userServiceV2Weight)
.and()
.path("/api/users/**")
.uri("https://user-service-v2.com")
}
.build()
}
}yaml
gateway:
routes:
user:
weight: 80
user-v2:
weight: 20
spring:
cloud:
gateway:
routes:
- id: user_service_v1
uri: https://user-service-v1.com
predicates:
- Weight=user_service_group, ${gateway.routes.user.weight}
- Path=/api/users/**
- id: user_service_v2
uri: https://user-service-v2.com
predicates:
- Weight=user_service_group, ${gateway.routes.user-v2.weight}
- Path=/api/users/**总结
Spring Cloud Gateway 的路由谓词工厂为微服务架构提供了强大而灵活的请求路由能力。通过合理使用不同类型的谓词工厂,我们可以实现:
- 🕒 基于时间的路由:定时发布、限时活动、维护窗口
- 🌐 基于请求属性的路由:多租户、API 版本控制、设备类型区分
- 🔒 基于网络的路由:安全控制、地理位置路由、内外网隔离
- ⚖️ 基于权重的路由:灰度发布、蓝绿部署、负载均衡
掌握这些谓词工厂的使用,能够帮助我们构建更加智能、灵活、可靠的微服务网关系统。在实际应用中,建议根据具体业务需求组合使用多个谓词工厂,并注意路由顺序、性能优化和监控调试等方面的最佳实践。