Skip to content

LocalResponseCache 网关过滤器工厂

概述

LocalResponseCache 用于缓存下游服务的响应内容,从而显著提升网关的性能和响应速度。

该过滤器只有在 `spring.cloud.gateway.filter.local-response-cache.enabled` 属性启用时才可用。

业务场景

在实际的微服务架构中,网关经常需要处理大量重复的请求,特别是:

  • 商品信息查询:电商系统中用户频繁查看商品详情
  • 配置信息获取:移动端应用启动时获取配置信息
  • 静态数据查询:查询地区列表、分类信息等不经常变化的数据
  • 报表数据:定时生成的报表数据,短时间内不会变化

通过使用 LocalResponseCache 过滤器,可以有效减少对下游服务的请求压力,提升用户体验。

缓存规则

该过滤器遵循以下缓存规则:

请求类型限制

  • 仅支持无请求体的 GET 请求:只有 GET 请求且不包含请求体的情况下才会缓存

状态码限制

缓存仅适用于以下 HTTP 状态码:

  • 200 OK - 成功响应
  • 206 Partial Content - 部分内容响应
  • 301 Moved Permanently - 永久重定向

Cache-Control 头部控制

响应不会被缓存的情况:

  • 请求中包含 Cache-Control: no-store
  • 响应中包含 Cache-Control: no-storeCache-Control: private

缓存验证

  • 当缓存存在且新请求包含 Cache-Control: no-cache 时,返回 304 Not Modified 状态码

工作流程

配置方式

1. 添加依赖

首先需要添加必要的依赖:

kotlin
dependencies {
    implementation("com.github.ben-manes.caffeine:caffeine")
    implementation("org.springframework.boot:spring-boot-starter-cache")
}

2. 启用缓存功能

application.yml 中启用本地响应缓存:

yaml
spring:
  cloud:
    gateway:
      filter:
        local-response-cache:
          enabled: true

3. 路由配置

kotlin
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
import java.time.Duration

@Configuration
class GatewayRouteConfiguration {

    @Bean
    fun routes(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            .route("product_cache_route") { r ->
                r.path("/api/product/**")
                    .filters { f ->
                        f.prefixPath("/v1")
                            // 缓存30分钟,最大缓存大小500MB
                            .localResponseCache(Duration.ofMinutes(30), "500MB")
                    }
                    .uri("http://localhost:8081")
            }
            .route("config_cache_route") { r ->
                r.path("/api/config/**")
                    .filters { f ->
                        f.localResponseCache(Duration.ofHours(1), "100MB") // 配置信息缓存1小时
                    }
                    .uri("http://localhost:8082")
            }
            .build()
    }
}
java
@Configuration
public class GatewayRouteConfiguration {

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("product_cache_route", r -> r.path("/api/product/**")
                .filters(f -> f.prefixPath("/v1")
                    .localResponseCache(Duration.ofMinutes(30), "500MB"))
                .uri("http://localhost:8081"))
            .route("config_cache_route", r -> r.path("/api/config/**")
                .filters(f -> f.localResponseCache(Duration.ofHours(1), "100MB"))
                .uri("http://localhost:8082"))
            .build();
    }
}

4. YAML 配置方式

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: product_service
          uri: http://localhost:8081
          predicates:
            - Path=/api/product/**
          filters:
            - LocalResponseCache=30m,500MB # 30分钟,500MB

        - id: config_service
          uri: http://localhost:8082
          predicates:
            - Path=/api/config/**
          filters:
            - LocalResponseCache=1h,100MB # 1小时,100MB

参数说明

时间参数 (TTL)

  • s - 秒(seconds)
  • m - 分钟(minutes)
  • h - 小时(hours)

大小参数

  • KB - 千字节
  • MB - 兆字节
  • GB - 千兆字节

实际业务示例

电商商品详情缓存

kotlin
@Configuration
class ECommerceGatewayConfig {

    @Bean
    fun eCommerceRoutes(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            // 商品详情页 - 缓存较长时间
            .route("product_detail") { r ->
                r.path("/api/product/{id}")
                    .and().method("GET")
                    .filters { f ->
                        f.localResponseCache(Duration.ofMinutes(30), "200MB")
                            .addRequestHeader("X-Gateway-Cache", "product-detail")
                    }
                    .uri("http://product-service:8080")
            }
            // 商品列表 - 缓存时间较短
            .route("product_list") { r ->
                r.path("/api/product/list")
                    .and().method("GET")
                    .filters { f ->
                        f.localResponseCache(Duration.ofMinutes(5), "100MB")
                            .addRequestHeader("X-Gateway-Cache", "product-list")
                    }
                    .uri("http://product-service:8080")
            }
            .build()
    }
}

移动应用配置缓存

kotlin
@Configuration
class MobileAppGatewayConfig {

    @Bean
    fun mobileAppRoutes(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            // 应用配置信息 - 长时间缓存
            .route("app_config") { r ->
                r.path("/api/mobile/config")
                    .filters { f ->
                        f.localResponseCache(Duration.ofHours(2), "50MB")
                            .addResponseHeader("X-Cache-Type", "app-config")
                    }
                    .uri("http://config-service:8080")
            }
            // 地区数据 - 超长时间缓存
            .route("region_data") { r ->
                r.path("/api/region/**")
                    .filters { f ->
                        f.localResponseCache(Duration.ofHours(24), "20MB")
                    }
                    .uri("http://region-service:8080")
            }
            .build()
    }
}

Cache-Control 头部处理

该过滤器会自动计算和更新 HTTP `Cache-Control` 头部中的 `max-age` 值。

自动计算 max-age

示例场景

kotlin
// 假设配置的 TTL 为 30 分钟
.localResponseCache(Duration.ofMinutes(30), "100MB")

// 第一次请求时,响应头会包含:
// Cache-Control: max-age=1800 (30分钟 = 1800秒)

// 10分钟后的请求,响应头会更新为:
// Cache-Control: max-age=1200 (剩余20分钟 = 1200秒)

高级配置

自定义 CacheManager

kotlin
@Configuration
class CacheConfiguration {

    @Primary
    @Bean("gatewayCacheManager")
    fun gatewayCacheManager(): CacheManager {
        val cacheManagerBuilder = Caffeine.newBuilder()
            .maximumSize(1000) // 最大缓存条目数
            .expireAfterWrite(Duration.ofMinutes(30)) // 写入后过期时间
            .recordStats() // 启用统计信息

        return CaffeineCacheManager().apply {
            setCaffeine(cacheManagerBuilder)
            setCacheNames(listOf("gateway-response-cache"))
        }
    }
}

缓存监控

kotlin
@Component
class CacheMonitor {

    @Autowired
    @Qualifier("gatewayCacheManager")
    private lateinit var cacheManager: CacheManager

    @Scheduled(fixedRate = 60000) // 每分钟输出一次缓存统计
    fun logCacheStats() {
        val cache = cacheManager.getCache("gateway-response-cache")
        if (cache is CaffeineCache) {
            val stats = cache.nativeCache.stats()
            logger.info("""
                缓存统计信息:
                命中率: ${String.format("%.2f%%", stats.hitRate() * 100)}
                命中次数: ${stats.hitCount()}
                未命中次数: ${stats.missCount()}
                缓存大小: ${cache.nativeCache.estimatedSize()}
            """.trimIndent())
        }
    }

    companion object {
        private val logger = LoggerFactory.getLogger(CacheMonitor::class.java)
    }
}

注意事项

如果项目中创建了自定义的 `CacheManager` bean,需要使用 `@Primary` 注解标记或通过 `@Qualifier` 注入。

缓存可能会占用大量内存,请根据实际情况合理设置缓存大小和过期时间。

最佳实践

  1. 合理设置缓存时间

    • 静态数据:1-24 小时
    • 准静态数据:10-60 分钟
    • 动态数据:1-5 分钟
  2. 监控缓存性能

    kotlin
    // 添加缓存性能监控
    @EventListener
    fun handleCacheEvictEvent(event: CacheEvictEvent) {
        logger.info("缓存清除事件: 键=${event.key}, 原因=${event.cause}")
    }
  3. 缓存预热

    kotlin
    @Component
    class CacheWarmupService {
    
        @PostConstruct
        fun warmupCache() {
            // 应用启动时预热常用数据
            preloadProductCategories()
            preloadSystemConfig()
        }
    
        private fun preloadProductCategories() {
            // 预加载商品分类数据
        }
    }

故障排除

常见问题

  1. 缓存未生效

    • 检查是否启用了 local-response-cache.enabled
    • 确认请求是 GET 方法且无请求体
    • 验证响应状态码是否为 200/206/301
  2. 内存占用过高

    • 调整缓存大小参数
    • 缩短缓存过期时间
    • 检查是否有内存泄漏
  3. 缓存数据不一致

    • 合理设置缓存过期时间
    • 考虑使用分布式缓存
    • 实现缓存主动清除机制
Details

调试技巧启用 Gateway 的调试日志来观察缓存行为:

yaml
logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    org.springframework.cache: DEBUG

总结

LocalResponseCache 过滤器是 Spring Cloud Gateway 提供的强大缓存解决方案,能够显著提升网关性能。通过合理配置缓存策略,可以在保证数据一致性的前提下,大幅减少对下游服务的请求压力,提升整体系统的响应速度和用户体验。

在实际使用中,需要根据业务特点合理设置缓存参数,并做好监控和故障排除,以确保缓存机制能够发挥最大效用。