作者:三辰
前言
大家好,今天给大家带来 MSE 高可用方向的重要功能——风险管理的发布。
阅读这篇文章,你将能够了解以下知识点和能力:
- 熟悉微服务体系高可用如何设计
- 掌握如何控制系统中的风险
- 了解MSE微服务引擎风险管理功能能解决什么风险
- 熟悉如何使用风险管理功能
- 了解风险管理更多高级功能的未来规划
微服务高可用如何设计
大促场景如何做高可用
阿里巴巴十几年的大促经验,积累了一套成熟的微服务高可用评估体系。
我们现在以大促场景为例,谈谈如何做好高可用。
大促高可用
首先从架构上看,内部的电商、物流、文娱等业务系统,都是基于 MSE 微服务引擎提供的云原生网关和 Nacos 注册配置中心构建的微服务体系。并且在整个链路上基于 MSE 的 Sentinel 覆盖限流降级的能力,基于 ARMS 的 Prometheus 和 Tracing 能力做好链路的可观测。
底层容器化,基于 K8s 这一套成熟的调度体系,解决资源利用率、快速交付和弹性的问题。
在大促即将到来之前,通过 PTS 提供的全链路压测能力,对整个大促涉及的所有链路进行端到端的压测,模拟真实大促流量,观测每个业务子系统的表现,验证限流降级预案执行准确无误。峰值前快速弹性上线,峰值后快速缩容下线。
MSE 微服务引擎介绍
基于这一套双十一大促实践经验,阿里中间件团队将这一套微服务最佳实践开源,并提供了一套完整的商业化解决方案。以满足外部客户对高性能、高可用、高集成度和安全的述求。
微服务引擎(Micro Service Engine,简称 MSE)是一个面向业界主流开源微服务生态的一站式微服务平台。
高可用设计思路
- 系统组成
那么,一套微服务系统如果从零开始搭建,应该如何设计保证高可用呢?
我们用一张简单的图来表示一个微服务系统的基本架构。
微服务系统全链路包含网关、注册配置中心、业务子系统,任何地方都是「牵一发而动全身」,一个抖动都可能会较大范围地影响整个系统。
每个业务子系统之间调用关系通常也非常复杂,甚至是网状的。
- 可能发生什么问题?
这套最小系统的每一个部分都可能发生问题,我们来看看都有哪些。
先从入口的网关来看,最典型的问题就是容量不足,导致吞吐量下降。表现就是用户访问系统出现超时;也有可能是错配导致流量丢失,用户访问的页面找不到打不开,比如最流行的 Nginx,没有页面操作,都是黑屏控制,很容易出现漏配、错配的问题,也缺少配置版本的管理,非常容易失误。
注册中心故障,会导致注册失败,影响大促场景下快速弹性上线,新的容器都无法注册上来。在服务调用方还可能收到空列表的情况。
配置中心出问题,会导致风险预案无法下发,不能对业务降级。
业务子系统更加复杂,可能出现某个子系统流量瓶颈,拖垮整个流量的情况。业务异常缺少观测手段,该打日志的地方没有任何信息。这些都需要借助服务治理的能力解决。
这些问题都是以往的大促活动中真实案例,每一个高可用方案的背后,都是一段血泪史。
- 面对风险设计
我们不得不承认一个事实:没有任何系统是百分之百没有问题的。
高可用架构就是面对失败设计,或者说是面对风险设计。
基础设施意外风险,最典型的就是几年前,杭州某条光缆被地铁施工挖断,导致全国的支付宝都用不了。这种风险一旦发生,业务很难承受。
还有操作系统依赖上,可能有存储故障、网络抖动、时间服务不稳定、DNS 故障等等,系统 hang 死了连监控报警都有可能上不来。
还有业务系统服务端故障、内存泄露,客户端连接池满,运维人为误操作等。
虽然我们不可避免风险发生,但是,我们可以控制风险。
高可用的本质:控制风险
如何控制风险
风险控制的策略
大致可以分为四种策略控制风险,如下图:
有了相应的策略,我们如何提前识别风险并加以控制?
识别不同风险
我们把风险分成几类:
- 架构风险
- 版本风险
- 容量风险
- 安全风险
架构风险
例如:
- 注册配置中心、网关、业务系统单节点都无法高可用
- Nacos、ZK等注册中心一致性协议对双数节点存在无法选主的问题,写请求不可用
- 注册中心节点在可用区分布不均,可用区故障可能导致集群不可用
- 业务系统架构风险:无注册中心容灾措施(如推空保护、服务列表缓存&降级方案)
这些都可以算作架构风险。
- MSE 注册配置中心三 AZ 容灾架构
MSE 专业版的注册配置中心,默认采用三可用区部署的容灾架构。通过 3 副本解决了单点问题,以多可用区部署的方式来减少了单一可用区不可用的风险带来的影响。集群所依赖的网络和存储实例,也都是多可用区部署的架构。
这就是一个云上服务做高可用容灾的典型架构。开发者的业务架构也同样可以 follow 这个模式。
- 业务架构风险
说到业务架构,通常一个网格状的业务调用关系,一定会有服务消费者(Consumer)和服务提供者(Provider)。
1. Consumer
服务消费者(Consumer)会从注册中心上订阅服务提供者(Provider)的实例列表。
当遇到突发情况(例如,可用区断网,Provider 端无法上报心跳) 或 注册中心(变配、重启、升降级)出现非预期异常时,都有可能导致订阅异常,影响服务消费者(Consumer)的可用性。
为了应对不可预知的情况下订阅列表异常,可以在 Consumer 侧配置推空保护。
我们来看一下什么是 Consumer 端的推空保护。
当 Provider 端到 Nacos 注册中心的网络出现异常,或是注册中心自身运维上下线过程中,维护的 Provider 实例列表可能出现空的情况,推送到 Consumer 端。这时,Consumer 侧订阅到了空的 Provider 列表,就会导致业务中断。
如果在 Consumer 侧配置推空保护,收到空列表时会丢弃这次异常的更新操作,仍然保持上一次非空列表,确保业务调用链路的流量正常往下走。
开启的方式非常简单,无论是 SCA 还是 Dubbo 框架,一个配置即可开启。
推空保护支持的版本要求大家可以在我们 MSE 的高可用最佳实践帮助文档当中找到。
Consumer 第二个有效措施是服务降级。
Consumer 端可以根据不同的策略选择是否将某个调用接口降级,起到对业务请求流程的保护(将宝贵的下游 Provider 资源保留给重要的业务 Consumer 使用)
服务降级的具体策略,包含返回 Null 值、返回 Exception 异常、返回自定义 JSON 数据和自定义回调
这个降级过程是全自动,无需干预的过程。只要配置的策略被触发了,治理平台会自动执行预案,并且可以在控制台上清楚地观测到。
2. Provider
服务提供者(Provider)自身的可用性遇到问题,需要紧急下线,或者是日常运维上下线时,实例列表在注册中心上的更新不及时导致流量有损,就需要一系列措施来保障它的高可用。
- 离群实例摘除
心跳续约是注册中心感知实例可用性的基本途径。Provider 在大流量下可能出现异常,但有时候服务不是完全不可用,它与注册中心之间的心跳续约仍然存在,但是某些系统资源耗尽是简单的心跳机制无法感知的。例如:
- Request 处理的线程池满
- 依赖的 RDS 连接异常或慢 SQL
微服务治理中心提供离群实例摘除:
- 基于异常检测的摘除策略:包含网络异常和网络异常 + 业务异常(HTTP 5xx)
- 设置异常阈值、QPS 下限、摘除比例下限
离群实例摘除的能力是一个补充,根据特定接口的调用异常特征,来衡量服务的可用性。降级过程完全自动。
- 无损上下线
通常我们不做任何措施的情况下,我们的服务上下线都是有损的。
有损下线
无损下线,又叫优雅下线、或者平滑下线,都是一个意思。首先看什么是有损下线:
Provider 实例进行升级过程中,下线后心跳在注册中心存约以及变更生效都有一定的时间,在这个期间 Consumer 端订阅列表仍然没有更新到下线后的版本,如果鲁莽地将 Provider 停止服务,会造成一部分的流量损失。
无损下线
可以通过 MSE 微服务治理平台的能力,开启无损上下线。无侵入、无改造地无感开启。
无损下线的流程整合在发布流程中,对应用进行停止、部署、回滚、缩容、重置等操作时,无损下线会自动执行。免去繁琐的运维脚本逻辑的维护。
版本风险
任何软件版本都有一个迭代过程,不断增强功能和优化的过程当中,也会无意中引入一些问题。在我们 Nacos 过去发布的版本当中,就存在一些客户端版本在特定条件下会出现严重问题的缺陷。例如:Nacos-Java-Client:v1.4.1 DNS 失败后心跳线程无法自愈;或者是一些社区维护的多语言版本客户端,存在一些功能的缺失。
服务端版本也是同样的。由 MSE 专业的商业化团队维护,无论是注册中心还是网关都在不断地迭代收敛各类性能问题和功能缺陷,版本总是越发展越趋向于稳定,一些过去存在严重缺陷的版本,我们也会通过这次发布的风险管理功能给开发者们透出。
- 案例
某客户在阿里云上使用 K8s 集群部署了许多自己的微服务,但是某一天,其中一台节点的网卡发生了异常,最终导致服务不可用,无法调用下游,业务受损。
- ECS 故障节点上运行着 K8s 集群的核心基础组件 CoreDNS 的所有 Pod,它没有打散,导致集群 DNS 解析出现问题。
- 该客户的服务发现使用了有缺陷的客户端版本(nacos-client 的 1.4.1 版本),这个版本的缺陷就是跟 DNS 有关——心跳请求在域名解析失败后,会导致进程后续不会再续约心跳,只有重启才能恢复。
- 这个缺陷版本实际上是已知问题,阿里云在 5 月份推送了 nacos-client 1.4.1 存在严重 bug 的公告,但客户研发未收到通知,进而在生产环境中使用了这个版本。
案例中存在的风险:
- CoreDNS 没有按节点打散,单点架构风险
- 依赖客户端版本风险没有被通知,没有有效收敛
容量风险
容量评估一直是一个复杂的事情。
每年每个大促,阿里内部都会做一次全链路的压测,目的就是确保每个业务和系统的容量做到最佳的评估。容量风险带来的雪崩效应能够像洪水一样,瞬间摧毁整个系统。
说它复杂,是因为每个子系统都有不同的评估指标和标准。
- 注册中心:Provider 数量、连接数、QPS/TPS
- 配置中心:配置长轮询数、连接数、QPS/TPS
- 网关:并发连接数、新建连接数、带宽、QPS
- 不同条件下(短/长连接、包大小、是否 https/gzip)的 QPS 容量是不同的
- 真实条件更加复杂
- 业务系统:吞吐能力(QPS/TPS/RT)、上下游依赖的处理能力
比如注册中心关注 Provider 数量、连接数、TPS;配置中心关注长轮询请求的量;网关更加复杂,并发连接数、新建连接数、带宽、QPS;甚至不同条件下,比如请求是长连接还是短连接、每个 HTTP 包的大小、是否是 HTTPS、是否 gzip 压缩,都是影响容量上限的因素。
业务系统除了需要评估自身的吞吐能力之外,还需要关注上下游依赖的处理能力,遵循木桶原理,通过全链路压测的方式,来找到那个短板。
- 网关容量评估策略
这里简单分享一个大促下网关的容量评估方法。
大促的特点是什么?
第一个是瞬时流量非常高,秒级突发流量,我们需要做好过载保护的限流措施,除了正常流量之外,还需要预留好足够的容量水位应对突发的网络攻击。
第二个是大促会有热点商品,网关针对热点商品提前预热流量,确保底层业务系统处于最佳状态。
第三个是梳理和保障核心链路,大促期间,一些非主链路的,锦上添花的功能就可以直接在网关侧降级掉,避免不必要的流量打到业务系统上。
我举一个我自己体会很深的一个例子,就是钉钉当时因为疫情,学校都通过钉钉在家上网课,为了保障核心视频链路的通畅,所有无关的功能就被降级掉了。比如表情标签,点赞这些功能,一般人不会因为不能点赞而抱怨功能异常产生舆情,降级也是合理的。
安全风险
开源产品总会时不时报出安全漏洞,无论是产品自身还是第三方依赖。
- 注册中心(Nacos、ZooKeeper)、网关(Envoy)相关安全漏洞
- 客户端的第三方依赖漏洞(log4j 等)
安全能力:
- 注册配置中心公网 Endpoint 白名单 ACL 控制
- MSE 云原生网关获得信通院安全评级认证
- 网关支持 WAF 本地防护
目前,MSE 已经具备较高的安全能力。
很多客户都为了调试方便,注册配置中心的公网 Endpoint 没有设置 ACL,容易被攻击。我们建议将 ACL 开启。
网关支持本地 WAF 等防护能力,并且获得了信通院安全评级认证。
风险管理功能介绍
到这里,大家应该充分掌握了如何有效地控制系统中的风险。
本次 MSE 发布的风险管理功能,目地就是让开发者能够简单高效地识别和控制风险,给大家一个 MSE 产品相关的风险控制的最佳实践指导。
功能页面
风险管理已覆盖 MSE 中 Nacos、ZooKeeper、云原生网关三大子产品。在实例页面中的菜单上可以找到:
针对每一个实例,我们会给出当前实例的风险列表,覆盖架构、版本、容量、安全等方面。
每个风险都会给出相应的解决方案和建议,如果需要扩容或升配,建议在业务低峰期操作。
未来规划
过去,风险的识别都依赖人工感知,甚至滞后,到了风险发生时再采取措施就为时已晚了。
现在,MSE 相关产品都已经能够做到系统自动化的识别风险信息,并且主动推送到使用产品的负责人。
我们完成了风险识别、透出、诊断链路的建设,后续还会不断建设完善更多的诊断方式,增加对风险的识别能力。
未来,我们还会探索风险自愈能力的建设。我们希望把一些明确的风险问题能够做到自愈,让用户无需感知风险收敛的过程。
感知容量风险,自动弹性;在可运维时间内无感知自愈;提供一个用户可主动订阅的事件中心,帮助用户快速感知异常事件。
作者介绍:
三辰,云原生微服务基础架构技术专家、MSE 架构-高可用负责人。
更多 MSE 特性,欢迎进钉钉群交流~