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
相关推荐
历程里程碑8 小时前
C++ 4:内存管理
java·c语言·开发语言·数据结构·c++·笔记·算法
没有bug.的程序员8 小时前
微服务的本质:不是拆服务,而是拆复杂度
java·jvm·spring·微服务·云原生·容器·架构
武子康8 小时前
Java-200 RabbitMQ 架构与 Exchange 路由:fanout/direct/topic/headers
java·架构·消息队列·系统架构·rabbitmq·java-rabbitmq·mq
计算机学姐8 小时前
基于SSM的社区外来务工人员管理系统【2026最新】
java·vue.js·java-ee·tomcat·maven·intellij-idea·mybatis
ForteScarlet8 小时前
Kotlin 2.3.0 现已发布!又有什么好东西?
android·开发语言·后端·ios·kotlin
好学且牛逼的马8 小时前
HttpServlet 深度拆解:从设计模式看透其核心原理
java·servlet·设计模式
顾安r8 小时前
12.17 脚本网页 创意导航
java·linux·前端·游戏·html
Json____8 小时前
springboot框架对接物联网,配置TCP协议依赖,与设备通信,让TCP变的如此简单
java·spring boot·后端·tcp/ip
洛阳泰山8 小时前
快速上手 MaxKB4J:开源企业级智能知识库系统在 Sealos 上的完整部署指南
java·开源·llm·agent·rag