服务发布
问题:
- 服务不可用
- 服务抖动
- 服务回滚
解决方案:
- 蓝绿部署:简单稳定,但需要两倍资源,结合高低峰,比较适合在低峰时采用蓝绿部署
- 灰度发布(金丝雀发布):先上线一个新实例,看有没有问题,然后下线一个,更新一个,下线一个,更新一个。不需要两倍的资源,但得不断地精细地切换流量;回滚也很有难度,1%到99%都可能回滚,k8s提供了这个能力。
流量治理
在微服务架构下,我们可以基于地区、集群、实例、请求等维度,对端到端流量地路由路径进行精确控制。 可以基于不同地区(北京上海),集群(稳定集群/测试集群),机器(新老机器),内部外部请求(内部请求可以特殊标识,发到测试实例上)
负载均衡
负载均衡负责分配请求在每个下游实例上的分布。 常见的load balance策略:
- round robin
- random
- ring hash
- least request
稳定性治理
线上服务总是会出问题,这与程序正确性无关。
- 网络攻击
- 流量突增
- 机房断电
- 光纤被挖
- 机器故障
- 网络故障
- 机房空调故障
保护机制:
- 限流:流量太大了,拒绝掉一部分
- 熔断:当服务B出现问题,服务A不会不断地再去连服务B,拒掉这些流量,然后间隔时间尝试连接
- 过载保护:服务B CPU 99%了,主动拒绝一部分流量
- 降级:保证重要的流量,服务B中degrade组件识别流量等级,拒掉降级掉的流量
字节跳动重试方面的实践
重试的意义:本地函数调用没有重试的必要;远程函数调用有重试的必要,因为可能是以下原因:
- 网络抖动
- 下游负载高导致超时
- 下游机器宕机
- 本地机器负载高
- 调度超时下游熔断、限流
重试可以避免偶发的错误,降低长尾请求延时(重试请求有机会提前返回)
难点:
- 幂等性
- 重试风暴:调用链路长,每一层都重试N次,M层就会重试N的M次方次。很小的问题导致雪崩。
- 方案:
- 设定重试比例(重试次数占所有请求比例不超过一个阈值,如1%)
- 防止链路重试:理想情况只有最下面一层重试,可以返回特殊的status:“请求失败,但别重试”
- hedged request对冲请求:对于可能超时(或延时高)的请求,重新向另一个下游实例发送相同的请求,等待先到达的相应
- 方案:
- 超时设置