Go 微服务可用性设计
本文最后更新于:2 年前
Go 微服务可用性设计知识点
隔离
服务隔离
动静隔离
如 CND 缓存加速、mysql LRU 算法改进
业务可以拆成两张表,静态表(字段机会不会改)和动态表(字段经常改)
读写隔离
- 主从
- CQRS
轻重隔离
- 核心:服务按核心与否进行分离,越核心的服务可用性要求也高
- 快慢
- 热点
- 小表广播: 存为到内存,定期更新
- 主动预热:旁路预热
物理隔离
- 线程:使用线程池,不同业务逻辑用不同的池子
- 进程:容器化
- 集群:region.zone.cluster.appid
- 机房
超时控制
核心理念: fail fast
起因
- 网络具有不确定性
- 客户端和服务端不一致的超时策略
方案
- 进程内:每一个请求前查看是否有剩余时间,并继承超时策略
- 服务间: GRPC 支持基于 grpc-timeout 的 Header 传递
- 监控要看 95th、99th
过载保护
常见限流算法
- 令牌桶:按固定速率往桶里加令牌,可以消费多个令牌
- 漏斗桶: 按固定速率流出水滴,可以以任意速率流入水滴
痛点:阈值不好设置
自适应过载保护
inflight: 当前服务正在进行的请求数量(atomic.add 来加减)
pass: 每个采样窗口内成功的请求数
rt: 单个采样窗口的平均 响应时间
CPU 统计:使用独立的 goroutine 每隔 250ms 统计一次,计算均值时,使用简单滑动平均(考虑前一次的均值)去除峰值的影响
统计 CPU 的滑动均值作为启发阈值(如 80%),一旦触发进入过载保护阶段,算法:(pass * rt) < inflight
另外过载保护需要保证持续最小时间如 2s,以避免一个短时间的 CPU 下降可能导致大量请求被放行,严重是会打满 CPU
限流
定义:在一段时间内某个客户或应用可以处理多少个请求
作用:过滤流量峰值
常规方案
- 令牌桶:针对单个节点无法分布式限流
- QPS 限流:
- 不同的请求可能消耗的资源完全不同
- 静态阈值很难设置准确
- 使用 redis 分布式限流
- 单个大流量接口容易产生热点 key
- 每次请求需要拿一个 quota –> 优化:基于历史窗口数据批量拿 quota,减少请求 redis 频次
资源分配:Max-Min Fairness 算法
重要性 criticality
- 将请求按重要性分级,配额不足时,先拒绝优先级低的
- critical_plus
- critical
- sheddable_plus
- sheddable
- 通常 BFF 层接口分级,重要性可往下游传递
熔断: 客户端自适应节流
请求拒绝率: max(0, requests - K * accepts/(requests+1))
客户端流控
作用:避免 positive feedback 积极重试访问不可达的服务
- 限制请求频次,重试添加 backoff 退让策略
Gutter
gutter 集群只需要主集群的 10%的资源
主集群发生熔断被抛弃的请求会转移到 gutter 集群
如果 gutter 集群也接受不住流量,会重现抛到主集群
降级
本质为提供有损服务
通过降低回复的质量来答复以减少所需的计算量或时间
通常采用错误或者 CPU 指标作为决定性指标
通常在 BFF 层或网关来做
重试
随机化+指数避让
只应该在失败层重试,以免指数放大次数,如收到 503 就表示下游已重试过则直接往上抛结果当前层不在重试了
业务不幂等:尽量不重试,即使重试也需要避免数据发生重复
负载均衡
目标
- 均衡流量分发
- 识别异常节点
- 水平扩容
- 高可用 N+2
可能的问题
- 不同节点负载不一样
- 原因:
- 不同请求处理成本不一样
- 机器性能不一样
- 可能有节点 FullGC 中
- 多个 LB 中每个 LB 都没有全局视角
- 原因:
Power of Two Choices (P2C)
随机请两个节点进行打分,选择更优的节点
打分:服务端 CPU(通过 rpc response head 获取)、耗时、成功率,inflight
新加入节点开始权重较小,这个特性尤其对 Java 服务比较友好
指标计算结合滑动均值且使用时间衰减
最佳实践
变更管理:
70%的问题是由变更引起的,恢复可用代码并不总是坏事。
避免过载:
过载保护、流量调度等。
依赖管理:
任何依赖都可能故障,做 chaos monkey testing,注入故障测试。
优雅降级:
有损服务,避免核心链路依赖故障。
重试退避:
退让算法,冻结时间,API retry detail 控制策略。
超时控制:
进程内 + 服务间 超时控制。
极限压测 + 故障演练。
扩容 + 重启 + 消除有害流量。
references
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!