1.隔离
1.1介绍
隔离,本质上是对系统或资源进行分割,从而实现当系统发生故障时能限定传播范围和影响范围,即发生故障后只有出问题的服务不可用,保证其他服务仍然可用。
服务隔离
动静分离、读写分离
轻重隔离
核心、快慢、热点
物理隔离
线程、进程、集群、机房
1.2服务隔离
1.2.1动静分离
比如CDN场景中,将静态资源和动态API分离。
降低应用服务器负载,静态文件访问负载全部通过CDN。
对象存储存储费用最低。
海量存储空间,无需考虑存储架构升级。
静态 CDN 带宽加速,延迟低。
1.2.2读写分离
mysql读写分离,大家应该都知道。举另一个读写分离的例子,如下
archive: 稿件表,存储稿件的名称、作者、分类、tag、状态等信息,表示稿件的基本信息。
在一个投稿流程中,一旦稿件创建改动的频率比较低。
archive_stat: 稿件统计表,表示稿件的播放、点赞、收藏、投币数量,比较高频的更新。
随着稿件获取流量,稿件被用户所消费,各类计数信息更新比较频繁。
这样处理后,当我们想要获取统计信息的时候,就不需要通过count(*)来做统计了。
1.3轻重隔离
1.3.1核心隔离
核心业务应用单独部署,在k8s集群中,我们把核心业务应用部署在单独的节点上,其他会混和部署。
1.3.2快慢隔离
通过使用kafka,即使待处理的任务很多,消费端也是挨个处理。
1.3.3热点隔离
即热点新闻,热点直播
小表广播:
从 remotecache 提升为 localcache,app 定时更新,甚至可以让运营平台支持广播刷新 localcache。(使用atomic.Value进行copy-on-write)
主动预热:
比如直播房间页高在线情况下 bypass 监控主动防御。
1.4物理隔离
1.4.1线程隔离
1.4.2进程隔离
k8s中,一个应用会部署多个pod,每个pod都是单独的进程
1.4.3集群隔离
一个应用有多个实例,我们把部分实例部署在A集群,部分实例部署在B集群。这样A集群出问题,B集群的实例依旧正常工作。
1.4.4机房隔离
上云后,会通过多可用区隔离,避免一个可用区出问题,影响业务。
2.超时控制
2.1介绍
超时控制,我们的组件能够快速失效(fail fast),因为我们不希望等到断开的实例直到超时。没有什么比挂起的请求和无响应的界面更令人失望。这不仅浪费资源,而且还会让用户体验变得更差。我们的服务是互相调用的,所以在这些延迟叠加前,应该特别注意防止那些超时的操作。
超时控制是微服务可用性的第一道关,良好的超时策略,可以尽可能让服务不堆积请求,尽快清空高延迟的请求,释放 Goroutine。
2.2超时控制
在进行远程调用的时候,如http请求,redis请求,grpc请求等,我们都要设置下超时时间。
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
3.过载保护(后面补充)
4.限流(后面补充)
1.单机限流
2.分布式限流
3.熔断-客户端主动断开连接
4.客户端流控
5.降级
降级本质:提供有损服务
前端页面,非核心模块出问题的时候,例如:账户信息,可以返回默认的一些信息。
6.重试
1.限制重试次数和基于重试分布的策略(重试比率: 10%)。
2.随机化、指数型递增的重试周期: exponential ackoff + jitter。
3.client 测记录重试次数直方图,传递到 server,进行分布判定,交由 server 判定拒绝。
4.只应该在失败的这层进行重试,当重试仍然失败,全局约定错误码“过载,无须重试”,避免级联重试。
5.读重试,写尽量不要重试
7.负载均衡
总结
变更管理:
70%的问题是由变更引起的,恢复可用代码并不总是坏事。
避免过载:
过载保护、流量调度等。
依赖管理:
任何依赖都可能故障,做 chaos monkey testing,注入故障测试。
优雅降级:
有损服务,避免核心链路依赖故障。
重试退避:
退让算法,冻结时间,API retry detail 控制策略。
超时控制:
进程内 + 服务间 超时控制。
极限压测 + 故障演练。
扩容 + 重启 + 消除有害流量。