高可用:
- 一个系统在大部分时间都是可用的,即使发生硬件故障或者系统升级的时候。
- 评判标准就是可用时间占所有运行时间的比例或接口请求成功的比例。 优化方式
冗余设计
- 集群部署:减少单点故障
- 同城/异地灾备:多个备份数据放在同城/异地的不同机房中
- 同城/异地多活:相同服务多个服务部署在同城/异地不同机房中
- 故障转移:不可用服务快速自动的切换到可用服务,不需要人为干涉
限流
QPS 达到阈值进行控制,避免服务被流量高峰冲垮。
常见算法
- 固定滑窗:限定单位时间处理的请求数
- 优点:简单
- 缺点:
- 不够平滑,瞬间有高额请求打满时间窗口,后续的缓慢请求都处理不了,体验差
- 瞬间的高额请求可能超过系统处理上限,导致系统被瞬间击垮
- 滑动窗口:动态计算窗口请求数(会拆分成很多细小的窗口,每个窗口限流,窗口越多效果越好)
- 优点:不会出现边界高额请求
- 缺点:内存占用/计算复杂度变高
- 漏桶算法:使用固定长度队列保存请求,定期从队列中拿请求执行,超过队列长度就丢弃,强制平滑流量,输出速率绝对恒定
- 优点:简单,可以控制速率
- 缺点:无法利用空闲资源,即使系统空闲也只能以固定速率处理
- 令牌桶算法:所有请求被处理前需要拿到一个令牌,令牌有限的被放在桶中,请求处理结束后丢弃令牌,按照限流的速率给桶中添加令牌,桶满了就不再添加
- 优点:
- 可以限制平均速率和激增流量(最大值有限制),允许突发大流量,最大桶容量
- 可以动态调整令牌生成速率
- 缺点:
- 令牌生产速率/桶容量设置不合理,会导致大量请求被丢弃/系统过载
- 需要配合预热机制,否则初始桶是空的,瞬间的大量请求会被丢弃
- 优点:
对象
- IP:通过 req.headers['x-forwarded-for'] 获取请求的 ip ,可能被伪造,但是较为简单。
- 业务 ID:如用户 ID,当然可以根据 VIP 等级进行分层限流
限流中间件
- 单机:Guava
- 分布式:Sentinel 或者 Redis 或者 Nginx
降级和熔断
- 熔断机制
- 近期失败率过高,切换备用服务。
- 如Hystrix 和 Sentinel
超时和重试
- 超时:一个请求超过指定的时间还没有被处理的话,直接被取消并抛出指定的异常或者错误(比如
504),主要分为- 连接超时:连接建立最长等待时间
- 读取超时:请求处理最长等待时间
- 可以避免长时间阻塞或者内存泄露等问题
- 重试:一般在出现超时时进行,多次发送相同请求避免偶发性故障
- 固定间隔时间重试
- 梯度间隔时间重试:一般每次翻倍重试间隔
- 次数一般设置为 3,太多重试会给系统造成压力
- 重试幂等:比如用户支付超时,多次支付,需要每次支付时判定是否已经支付,已经支付跳过(即多次失败的重试最终成功应该结果和一次成功效果一样)
监控告警
- 异步调用
- 一般配合消息队列使用,请求之后立刻返回,可以通过邮件或者短信进行异步通知
- 配置监控告警
- 灰度发布
