分布式系统面试题:熔断、降级、限流
文章目录
一、熔断相关
1. 什么是熔断机制?它的工作原理是什么?
答案:
熔断机制就像电路中的保险丝。当系统出现故障时,自动切断服务调用,防止故障扩散。
工作原理:
- 监控服务调用失败率/响应时间
- 当失败率达到阈值(如50%),触发熔断
- 熔断后,所有调用直接返回错误,不再请求故障服务
- 经过一段时间(熔断窗口期),尝试放行少量请求测试
- 如果测试成功,逐步恢复;如果仍然失败,继续保持熔断
2. 熔断器有哪几种状态?状态之间如何转换?
答案:
熔断器有三种状态:
- 关闭状态(Closed):正常处理请求,统计失败率
- 开启状态(Open):直接拒绝请求,不调用下游
- 半开状态(Half-Open):尝试放行少量请求测试
状态转换:
- 关闭→开启:失败率超过阈值
- 开启→半开:熔断时间结束
- 半开→关闭:测试请求成功
- 半开→开启:测试请求仍然失败
3. Hystrix和Sentinel的熔断实现有什么区别?
答案:
Hystrix熔断:
- 基于线程池隔离
- 统计时间窗口内(默认10秒)的请求失败率
- 达到阈值后熔断,默认5秒后进入半开状态
Sentinel熔断:
- 支持更多熔断策略:慢调用比例、异常比例、异常数
- 统计滑动时间窗口内的指标
- 支持基于响应时间的熔断(慢调用比例)
- 资源定义更灵活,不限于方法调用
二、降级相关
1. 什么是服务降级?什么情况下需要降级?
答案:
服务降级是在系统压力过大或出现故障时,暂时关闭非核心功能,保证核心功能可用。
需要降级的场景:
- 系统流量激增,资源不足
- 依赖服务不可用
- 网络出现波动
- 系统发布或维护期间
2. 服务降级有哪些常见策略?
答案:
- 直接返回默认值:如商品详情页的评论功能不可用时显示"评论服务暂不可用"
- 缓存降级:使用缓存数据代替实时数据
- 功能屏蔽:关闭非核心功能,如双11关闭评价功能
- 异步改同步:将异步调用改为同步,减少线程占用
- 简化流程:跳过复杂计算,返回简化结果
3. 如何实现自动降级和手动降级?
答案:
自动降级:
- 通过熔断机制触发
- 监控系统指标自动决策
- 配置降级规则(如CPU>80%触发降级)
手动降级:
- 通过配置中心动态切换
- 运维人员手动触发
- 紧急开关(如大促前的预案)
实现方式:
- 配置中心(如Nacos、Apollo)存储降级开关
- AOP拦截请求,根据开关返回降级结果
- 结合熔断框架实现自动降级
三、限流相关
1. 常见的限流算法有哪些?各自原理是什么?
答案:
- 计数器算法:
- 最简单的限流,统计单位时间内的请求数
- 超过阈值就拒绝
- 问题:时间边界可能有突刺
- 滑动窗口算法:
- 将时间划分为更小的窗口(如1分钟分为6个10秒窗口)
- 统计最近N个窗口的请求量
- 更平滑,解决了计数器边界问题
- 漏桶算法:
- 想象一个漏水的桶,请求是水,以固定速率流出
- 桶满时新请求被丢弃/等待
- 严格控制请求速率
- 令牌桶算法:
- 系统以固定速率往桶里放令牌
- 请求需要拿到令牌才能执行
- 允许一定程度的突发流量(桶中有积累的令牌)
2. 分布式环境下如何实现限流?
答案:
分布式限流方案:
- Redis + Lua:
- 利用Redis的原子性
- 使用Lua脚本保证操作的原子性
- 实现计数器或令牌桶算法
- 中间件限流:
- 网关层限流(如Nginx、Spring Cloud Gateway)
- 使用Sentinel等框架的集群限流模式
- 分布式协调器:
- 通过Zookeeper等协调各节点限流配额
- 较复杂,一般不推荐
Redis限流示例原理:
- 使用Redis的incr命令统计请求数
- 设置过期时间实现时间窗口
- Lua脚本保证"读取-判断-写入"的原子性
3. 如何选择合适的限流阈值?
答案:
确定限流阈值的步骤:
- 压力测试:通过压测找出系统最大吞吐量
- 预留缓冲:取最大值的70%-80%作为阈值
- 动态调整:根据监控数据持续优化
- 分级限流:不同API设置不同阈值
考虑因素:
- 系统资源(CPU、内存、线程池等)
- 依赖服务的承受能力
- 业务优先级(核心API阈值更高)
- 时段因素(白天晚上阈值可能不同)
四、综合问题
1. 熔断、降级、限流三者的关系和区别是什么?
答案:
关系:
- 都是保护系统稳定性的手段
- 通常会配合使用
区别:
- 目标不同:
- 限流:控制流量,防止系统过载
- 熔断:防止故障扩散,快速失败
- 降级:保证核心功能,舍弃非核心
- 触发条件不同:
- 限流:流量过大时触发
- 熔断:依赖服务故障时触发
- 降级:系统资源不足或故障时触发
- 实现方式不同:
- 限流:计数器、令牌桶等算法
- 熔断:状态机模式
- 降级:开关配置、备用逻辑
2. 如何设计一个高可用的分布式系统防护体系?
答案:
分层防护设计:
- 接入层:
- Nginx限流
- WAF防护
- CDN抗流量攻击
- 网关层:
- 统一限流(Sentinel/Gateway)
- 身份认证/鉴权
- 请求过滤
- 服务层:
- 熔断机制(Hystrix/Sentinel)
- 线程池隔离
- 服务降级开关
- 资源层:
- 数据库连接池限制
- Redis连接限制
- 消息队列消费速率控制
其他措施:
- 全链路压测和容量规划
- 监控告警系统
- 应急预案和演练
- 灰度发布和回滚机制
3. 在实际项目中如何落地这些防护措施?
答案:
落地步骤:
- 评估系统风险点:
- 识别核心链路
- 找出性能瓶颈
- 分析依赖关系
- 制定防护策略:
- 确定哪些服务需要熔断
- 制定降级预案
- 设置合理的限流阈值
- 技术选型:
- 选择合适框架(Sentinel/Hystrix/Resilience4j)
- 确定配置中心(Nacos/Apollo)
- 设计监控方案(Prometheus/Grafana)
- 实施和测试:
- 代码实现防护逻辑
- 进行故障注入测试
- 全链路压测验证
- 监控和优化:
- 建立实时监控
- 定期演练
- 持续优化阈值和策略
注意事项:
- 防护措施本身不能成为瓶颈
- 避免过度防护影响正常业务
- 做好用户体验的平衡(如友好的降级提示)
- 文档化和团队培训