SpringCloud服务优雅下线LoadBalancer 缓存配置方案

LoadBalancer 缓存配置方案

问题场景

当服务从注册中心(如 Nacos)注销后,客户端仍然会继续调用已下线的服务实例,导致请求失败。

时间线示例:

复制代码

14:34:04 service-provider 从 Nacos 注销服务 14:34:15 service-consumer 服务还在调用已注销的服务,报错

错误信息:

复制代码

feign.RetryableException: No route to host (Host unreachable) executing GET http://service-provider/api/health Caused by: java.net.NoRouteToHostException: No route to host (Host unreachable)

根本原因

Spring Cloud LoadBalancer 会缓存服务实例列表,默认缓存时间(TTL)为 35 秒

工作流程:

复制代码

1. 首次获取服务实例列表 → 写入缓存 2. 35 秒内 → 使用缓存的实例列表(不会查询注册中心) 3. 35 秒后 → 缓存过期,重新从注册中心获取

问题根源:

复制代码

服务下线时间点:T0 ├─ Nacos 注册中心:服务已注销 ✅ ├─ LoadBalancer 缓存:还有 20+ 秒才过期 ❌ └─ 客户端:继续使用缓存中的旧实例列表 ❌ ↓ 结果:调用已下线的服务 → 连接失败 → 超时异常

解决方案

配置 LoadBalancer 缓存时间

bootstrap.ymlapplication.yml 中配置:

复制代码

spring: cloud: loadbalancer: cache: ttl: 35s # 缓存过期时间,默认 35 秒 capacity: 256 # 缓存容量,默认 256

配置说明

1. ttl(Time To Live)
  • 作用:控制服务实例列表在本地缓存中的存活时间

  • 默认值35s(35 秒)

  • 单位:支持秒(s)、分钟(m)、小时(h)等

  • 工作流程

    复制代码


    首次获取 → 写入缓存 → ttl 时间内使用缓存 → ttl 后重新获取

2. capacity
  • 作用:设置缓存容量(最多缓存多少个服务的实例列表)
  • 默认值256
  • 说明:一般不需要修改

配置示例

示例 1:快速感知服务变化(开发/测试环境)
复制代码

spring: cloud: loadbalancer: cache: ttl: 5s # 5 秒后刷新缓存,快速感知服务变化

适用场景:

  • 开发环境
  • 测试环境
  • 需要快速感知服务变化的场景

优点:

  • 快速感知服务变化
  • 服务下线后最多 5 秒就能感知到

缺点:

  • 增加注册中心查询压力
  • 可能影响性能(频繁查询)
示例 2:平衡性能和实时性(生产环境推荐)
复制代码

spring: cloud: loadbalancer: cache: ttl: 35s # 默认值,平衡性能和实时性

适用场景:

  • 生产环境
  • 服务实例变化不频繁的场景

优点:

  • 减少注册中心查询压力
  • 性能友好
  • 35 秒的延迟通常可接受

缺点:

  • 服务下线后最多 35 秒才能感知到
示例 3:禁用缓存(不推荐)
复制代码

spring: cloud: loadbalancer: cache: ttl: 0s # 禁用缓存,每次都查询注册中心

适用场景:

  • 调试场景
  • 服务实例频繁变化的场景

优点:

  • 实时性最高
  • 立即感知服务变化

缺点:

  • 性能影响大(每次调用都查询注册中心)
  • 增加注册中心压力
  • 不适用于生产环境

配置建议

根据环境选择

环境 推荐 ttl 说明
开发环境 5s - 10s 快速感知变化,便于调试
测试环境 10s - 20s 平衡性能和实时性
生产环境 35s(默认) 性能优先,减少注册中心压力

根据业务场景选择

场景 推荐 ttl 说明
服务实例稳定 35s - 60s 实例变化少,可以设置较长缓存时间
服务实例频繁变化 10s - 20s 需要快速感知变化
高并发场景 35s - 60s 减少查询压力,提升性能
低延迟要求 5s - 10s 需要快速感知服务变化

注意事项

1. 缓存时间与优雅下线

如果使用优雅下线方案,需要确保:

复制代码

优雅下线等待时间 ≥ LoadBalancer 缓存 ttl + 缓冲时间(5-10秒)

示例:

复制代码

# LoadBalancer 配置 spring: cloud: loadbalancer: cache: ttl: 35s # 优雅下线配置(preStop Hook 或 @PreDestroy) sleep_time = 35s + 5s = 40s # 至少等待 40 秒

2. 缓存时间不宜过短

  • 过短 (如 1s):频繁查询注册中心,影响性能
  • 适中 (如 10s - 35s):平衡性能和实时性
  • 过长 (如 300s):服务变化感知延迟大

3. 监控缓存效果

建议监控以下指标:

  • 缓存命中率
  • 注册中心查询频率
  • 服务发现延迟

完整配置示例

生产环境配置

复制代码

spring: cloud: loadbalancer: cache: ttl: 35s # 缓存过期时间:35 秒 capacity: 256 # 缓存容量:256

开发环境配置

复制代码

spring: cloud: loadbalancer: cache: ttl: 5s # 缓存过期时间:5 秒(快速感知变化) capacity: 256 # 缓存容量:256

验证方法

1. 查看日志

配置后,可以通过日志观察服务实例列表的刷新:

复制代码

# 首次获取服务实例 [INFO] 已知的被调用方服务地址: 192.168.1.100:8080, 192.168.1.101:8080 # 服务下线后,等待 ttl 时间... # 缓存过期后,重新获取(已下线的服务不再出现) [INFO] 已知的被调用方服务地址: 192.168.1.101:8080

2. 测试服务下线

  1. 启动两个服务实例
  2. 观察客户端日志,确认能看到两个实例
  3. 下线一个服务实例
  4. 观察客户端日志,确认在 ttl 时间后,下线的实例不再出现

总结

核心要点

  1. LoadBalancer 缓存机制:默认缓存 35 秒,减少注册中心查询压力
  2. 配置位置spring.cloud.loadbalancer.cache.ttl
  3. 推荐值
    • 生产环境:35s(默认值)
    • 开发/测试环境:5s - 10s
  4. 注意事项 :如果使用优雅下线,需要确保等待时间 ≥ ttl + 缓冲时间

最佳实践

  • ✅ 生产环境使用默认值 35s
  • ✅ 开发/测试环境可以缩短到 5s - 10s
  • ✅ 配合优雅下线方案使用
  • ✅ 监控缓存效果和注册中心压力
  • ❌ 避免设置过短的缓存时间(< 3秒)
  • ❌ 避免在生产环境禁用缓存(ttl: 0
相关推荐
小璐猪头3 分钟前
专为 Spring Boot 设计的 Elasticsearch 日志收集 Starter
java
韩师傅5 分钟前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端
阿里巴巴P8资深技术专家14 分钟前
基于 Spring AI 和 Redis 向量库的智能对话系统实践
人工智能·redis·spring
ps酷教程23 分钟前
HttpPostRequestDecoder源码浅析
java·http·netty
闲人编程23 分钟前
消息通知系统实现:构建高可用、可扩展的企业级通知服务
java·服务器·网络·python·消息队列·异步处理·分发器
栈与堆43 分钟前
LeetCode-1-两数之和
java·数据结构·后端·python·算法·leetcode·rust
superman超哥1 小时前
双端迭代器(DoubleEndedIterator):Rust双向遍历的优雅实现
开发语言·后端·rust·双端迭代器·rust双向遍历
1二山似1 小时前
crmeb多商户启动swoole时报‘加密文件丢失’
后端·swoole
马卡巴卡1 小时前
Java CompletableFuture 接口与原理详解
后端
OC溥哥9991 小时前
Paper MinecraftV3.0重大更新(下界更新)我的世界C++2D版本隆重推出,拷贝即玩!
java·c++·算法