架构决定系统质量上限,代码决定系统质量下限
接口高可用整体框架
雪崩效应:请求量超过系统处理能力后导致系统性能螺旋快速下降
链式效应:某个故障引起后续一连串的故障
限流
用户请求全流程各个环节都可以限流:
- 请求端限流:发起请求的时候就可以进行限流,被限流的请求实际上并没有发给后端服务器
- 接入端限流:接到业务请求的时候进行限流,避免业务请求进入实际的业务处理流程
- 微服务限流:单个服务端的自我保护措施,处理能力不够的时候丢弃新的请求
具体实现方式
请求端限流
常见手段
- 限制请求次数,例如按钮变灰
- 嵌入简单业务逻辑,例如生成随机数
优缺点
- 实现简单
- 流量本地就控制住了
- 防正常用户,防止不了脚本
接入端限流
常见手段
- 限制同一用户请求频率
- 随机抛弃无状态请求,例如限流浏览请求,不限流下单请求
优缺点
- 实现复杂
- 可以防刷
- 限流阈值可能需要人工判断
微服务限流
常见手段
根据处理能力,丢去无法处理的请求
优缺点
- 实现简单
- 处理能力难以精准配置
限流算法
算法1:固定&滑动 时间窗
固定时间窗
设计原理
- 统计固定时间周期内的请求量,超过阈值则限流
- 存在临界点问题,如图中的红蓝两点对应的时间范围
滑动时间窗
设计原理
- 统计滑动时间周期内的请求量,超过阈值则限流
- 判断比较准确,但实现稍微复杂
算法2:漏桶
基本原理
请求放入“桶”(消息队列等),业务处理单元(线程/进程/服务)从桶里拿请求处理,桶满则丢弃新的请求
技术本质
总量控制,桶大小是设计关键
优缺点
- 桶大小动态调整比较困难,例如java BlockingQueue
- 无法精确控制流出速度(处理速度)
- 突发流量时丢弃的请求较少
应用场景
瞬间高并发流量,例如0点签到、整点秒杀
漏桶算法变种-写缓冲(Buffer)
基本原理
如果漏桶的容量无限(例如用kafka消息队列),则漏桶可以用来做写缓冲
技术本质
同步改异步,缓冲所有请求,慢慢处理
应用场景
高并发写入请求,例如热门微博评论
算法3:令牌桶
基本原理
某个处理单元按照指定速率将令牌放入“桶”(消息队列等),业务处理单元收到请求后需要获取令牌,获取不到就丢弃请求
技术本质
速率控制,令牌产生的速度是设计关键
优缺点
- 可以动态调整处理速度
- 突发流量的时候可以丢弃很多请求
- 实现相对复杂
典型应用场景
- 控制访问第三方服务的速度,防止把下游压垮
- 控制自己的处理速度,防止过载
排队
基本原理
收到请求后并不同步处理,而是将请求放入队列,系统根据能力异步处理
技术本质
请求缓存+同步改异步+请求端轮询
应用场景
秒杀、抢购
架构示意图
设计关键
- 如何设计异步处理流程
- 如何保证用户体验(前端、客户端交互)
具体实现方案示例
1号店双十一秒杀排队
降级
基本原理
直接停用某个接口或者URL,收到请求后直接返回错误(例如HTTP 503)
应用场景
故障应急,通常将非核心业务降级,保住核心业务,例如降级日志服务、升级服务等
架构实现
设计要点
- 独立系统操作降级,可以是独立的降级系统,也可以是嵌入到其他系统的降级功能
- 人工判断,人工执行
熔断
基本原理
下游接口故障的时候,一定时期内不再调用
应用场景
服务自我保护,防止故障链式效应
架构实现
实现细节
- 可以通过配置中心,也可以通过配置文件来配置熔断策略
- 熔断处理一般由框架或者SDK提供,例如Dubbo+Hystrix
- 熔断策略一般按照失败次数、失败比例、响应时长等来确定