Ribbon 开发随笔
Ribbon 超时控制与重试机制配置
在分布式系统中,服务拆分后,性能问题主要集中在 “服务间调用”,因此需要重点关注:
- 是否会超时
- 超时后是否重试,重试多少次
- 如何保证高可用(服务不被拖死)
超时 & 重试配置策略
- 超时控制(必须要有)
- 每个服务调用都会设置连接超时 + 读取超时
- 常见配置(以 Feign + Ribbon 为例):
1
2
3
4
5
6
7
8
9
10ribbon:
ConnectTimeout: 1000 # Ribbon建立连接超时时间(毫秒),比如 1000 毫秒
ReadTimeout: 3000 # Ribbon读取响应超时时间(毫秒),相当于最大业务处理时间,比如 2000 ~ 3000 毫秒
feign:
client:
config:
default:
connectTimeout: 1000 # Feign建立连接超时时间(毫秒),比如 1000 毫秒
readTimeout: 3000 # Feign读取响应超时时间(毫秒),相当于最大业务处理时间,比如 2000 ~ 3000 毫秒 - 配置原则:
- 超时时间不能太长(避免请求堆积)
- 也不能太短(避免误杀正常请求)
- 重试机制(谨慎使用)
- 是否重试取决于接口是否实现了幂等
- 配置策略:
- 幂等接口(查询类)
- 可以开启重试
1
2
3
4ribbon:
OkToRetryOnAllOperations: false # 是否对所有请求开启重试(开启后要求接口实现幂等)
MaxAutoRetries: 1 # 当前实例最大重试次数(0 表示不重试)
MaxAutoRetriesNextServer: 1 # 切换到其他实例的重试次数(0 表示不重试) - 非幂等接口(下单、支付)
- 不允许重试
1
2
3
4ribbon:
OkToRetryOnAllOperations: false # 是否对所有请求开启重试(开启后要求接口实现幂等)
MaxAutoRetries: 0 # 当前实例最大重试次数(0 表示不重试)
MaxAutoRetriesNextServer: 0 # 切换到其他实例的重试次数(0 表示不重试)
- 配置原因:
- 防止重复下单 / 数据错乱
Ribbon 首次调用超时问题
- 超时问题:
- 服务刚启动后
- 第一次调用很容易出现超时
- 超时原因:
- Ribbon 在第一次请求时才初始化
- 初始化耗时较长
- 解决方案:
- Ribbon 启用预热(Eager Load)
1
2
3ribbon:
eager-load:
enabled: true - Ribbon 启用预热后的效果:
- 服务启动时就初始化 Ribbon
- 避免第一次请求超时
- Ribbon 启用预热(Eager Load)
高可用保障(核心重点)
- Hystrix(或 Sentinel)
- 作用:
- 熔断
- 降级
- 线程池隔离(防止服务被拖死)
- 场景:
- 执行链路:
1
网关 → 订单服务 → 库存服务(卡住)
- 执行链路:
- 如果没有隔离:
- 请求会层层阻塞(级联故障)
- 最终导致网关返回
500 Internal Error
- 如果有隔离
- 库存服务卡住 → 订单服务直接熔断
- 订单服务返回降级结果(兜底数据)
- 配置(以 Hystrix 为例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25feign:
hystrix:
enabled: false # Feign是否启用Hystrix
client:
config:
default:
connectTimeout: 1000 # Feign建立连接超时时间(毫秒),比如 1000 毫秒
readTimeout: 3000 # Feign读取响应超时时间(毫秒),相当于最大业务处理时间,比如 2000 ~ 3000 毫秒
ribbon:
eager-load:
enabled: true
ConnectTimeout: 1000 # Ribbon建立连接超时时间(毫秒),比如 1000 毫秒
ReadTimeout: 3000 # Ribbon读取响应超时时间(毫秒),相当于最大业务处理时间,比如 2000 ~ 3000 毫秒
OkToRetryOnAllOperations: false # 是否对所有请求开启重试(开启后要求接口实现幂等)
MaxAutoRetries: 0 # 当前实例最大重试次数(0 表示不重试)
MaxAutoRetriesNextServer: 0 # 切换到其他实例的重试次数(0 表示不重试)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 # Hystrix在线程隔离模式下的超时时间(毫秒) - 特别注意:
- Hystrix Timeout > Ribbon ReadTimeout + 总重试时间
- 否则 Hystrix 先超时直接走 Fallback,而 Ribbon 还没执行完调用就被中断
- 作用:
特别注意
- Feign 本身默认是不负责重试的,重试是由 Ribbon 控制。Ribbon 主要通过
MaxAutoRetries和MaxAutoRetriesNextServer控制重试次数,并通过OkToRetryOnAllOperations控制是否对所有请求开启重试,避免重复执行写操作。 - Feign 和 Ribbon 都可以配置超时,但层级不同。Feign 主要是接口级配置,而 Ribbon 控制实际的服务调用过程,包括负载均衡和重试。在使用 Ribbon 时,实际生效的是 Ribbon 的超时配置。一般我们会以 Ribbon 的超时配置为主,同时保留 Feign 超时配置用于细粒度控制和兼容未来架构调整(比如,将 Ribbon 替换为 Spring Cloud LoadBalancer,或者直接使用 Feign + OkHttp)。
