这是我参与「第五届青训营 」笔记创作活动的第6天。此处为微服务的服务治理功能的简要介绍
服务发布
服务发布,即为让一个服务升级运行新的代码的过程。对于本地开发而言,我们只需要重新运行即可,但是对于在线服务来说,不可能直接 kill 服务重新运行。 服务发布的难点
- 服务不可用:当调用服务时,会发现服务提供方会停止服务,调用者会懵圈
- 服务抖动:如果服务的其中一个实例升级,此时如果把它关闭服务,这一部分流量会消失。
- 服务回滚:在升级完之后可能会有 bug,如果在本地开发,一般是查出 bug 之后再发布,但是在线环境中,这种方式不可取。对于在线环境来说,需要把版本回退,返回到前一个正确的版本中,尽可能减小损失。
解决方案
蓝绿部署
把服务分为两个集群,对应途中的蓝色和绿色区域。首先把绿色区域的流量断开,即全部的流量走蓝色通道,把绿色区域的实例进行升级后把通道转换为绿色,随后升级蓝色区域的实例,最后再放开蓝色的通道接受流量即可。 特点:简单、稳定,但在升级过程中,需要使用一半的实例处理原来的流量,直观上看,实例需要能够处理原来流量的两倍资源,所以这个方案比较适合在流量低估的情况进行
灰度发布(金丝雀发布)
背景:金丝雀 (canary)对瓦斯及其敏感,17 世纪时,英国旷工在下井前会先放入一只金丝雀,以确保矿井中没有瓦斯。
方案:依次加入一个新功能的实例,当加入新功能的实例后,下线一个旧实例,依次类推,直到全部的实例全部完成发布。如果再发布过程中出现 bug,则将所有已经发布的实例退回版本。
问题:
- 由于需要频繁的更新实例,而不是一次性完成,所以对注册中心的读写压力较大
- 服务的回滚比较困难,需要记录已经更新过的实例,如果在发布的最后时间出现了问题,则需要对全部已经发布过的实例执行回滚操作,开销比较高,并且对从基础设置要求比较高。由于 K8s 具有比较好的基础能力,所以是比较适配的。
流量治理
在微服务架构下,我们可以基于地区、集群、实例、请求等维度,对端到端流量的路由路径进行精确控制。
- 地区:API 网关会分布在不同的地区,且不同地区的实例有所差异,所以就需要分配地区流量分布。
- 集群:服务的集群中包含稳定的集群和测试的集群,一般稳定的集群分配的流量会更多,测试的集群流量可以理解为小白鼠,用于测试服务。
- 实例:对于一个服务中的实例之间也有新老之分,对于性能比较低的实例分配较少的流量。
- 请求类型:有些服务中包含公司内部 feature test 集群,当在请求中做一定的标记,对于标记为内部人员的流量放入 feature test 集群。这种请求的治理可以方便开发,为了测试服务,不需要把所有其他服务搭建一遍,对于测试很方便。
负载均衡
对于服务的每个实例来说,为了使得收到的流量对实例的负载压力是差不多的,需要添加 Load Balance 层负责分配流量到每个下游实例的分布。 常见的算法有:
- Round Robin
- Ring Hash
- Least Request
- Random
稳定性治理
线上服务总是会出问题的,这与程序的正确性无关,比如以下无法控制的问题:
- 网络攻击
- 流量突增
- 机房断电
- 光纤被挖
- 机器故障
- 网络故障
- 机房空调故障
典型的稳定性治理功能
为了优化系统以预防以上的问题,典型的治理功能有:限流、熔断、过载保护、降级
限流
当服务 A 发出的请求高于服务 B 的 Qps 时,服务 B 会使用 rate limit 组件将高出的流量请求拒绝在外。
熔断
类似于保险丝的功能,当服务 B 不可用时(连接异常),curcuit breaker (熔断器)会将上游的请求拒绝。服务 B 的后面会再次上线,熔断器会间断性的重试几次,直到可以访问服务 B 为止。
过载保护
当服务 B 所在的实例的压力过大时,服务 B 中的 dynamic overload 组件会主动拒绝一部分流量使得自己的压力降低。
降级
当服务 B 过载时。其 degrade 组件会识别流量的等级,拒绝等级较低的流量,比如线上的流量比内部开发的流量等级低,以保证终端的用户体验。