赞
踩
每年,网上都会报道XXX系统异常不可用,给客户带来巨大的经济损失。云服务的客户基数更大,一旦出现问题,都将给客户和服务自身带来极大影响。本文将基于华为云FunctionGraph自身的实践,详细介绍如何构建高可用的Serverless计算平台,实现客户和平台双赢。
高可用性[1](英语:high availability,缩写为 HA),IT术语,指系统无中断地执行其功能的能力,代表系统的可用性程度。是进行系统设计时的准则之一。
业界一般使用 SLA指标来衡量系统的可用性。
服务级别协议[2](英语:service-level agreement,缩写SLA)也称服务等级协议、服务水平协议,是服务提供商与客户之间定义的正式承诺。服务提供商与受服务客户之间具体达成了承诺的服务指标——质量、可用性,责任。例如,服务提供商对外承诺99.99%的SLA,则全年服务失效时间最大为 5.26 分钟(365*24*60*0.001%)。
FunctionGraph直观度量系统可用性的两个黄金指标,SLI和时延,SLI是系统的请求成功率指标,时延是系统处理的性能。
FunctionGraph作为华为云中的子服务,在构建自身能力的同时,不仅要考虑系统本身的健壮性,也要考虑周边依赖服务的健壮性(例如依赖的身份认证服务不可用了,进行流量转发的网关服务服务宕机了,存储对象的服务访问失败了等等)。除此之外,系统依赖的硬件资源故障或者系统突然遭到流量攻击等,面临这些不可控的异常场景,系统如何构建自己的能力来保持业务高可用是一个很大的挑战。图一展示了FunctionGraph的周边交互。
图1 FunctionGraph的周边交互
针对常见的问题,梳理出了4个大类,如表1所示。
故障大类 | 一级分类 | 二级分类 |
流量突变 | 正常流量突增 | 同步流量增加,底层资源不足 |
异步流量增加,消息队列资源不足 | ||
异常流量突增 | 函数时延突增,请求堆积飙升 | |
函数失败率飙升,重试请求飙升 | ||
系统服务异常 | 系统资源监控异常 | CPU飙升,无法处理新请求 |
内存飙升,无法处理新请求 | ||
客户流量飙升,客户互相干扰 | ||
系统进程监控异常 | 进程频繁重启,请求处理异常 | |
连接数飙升,无法处理新请求 | ||
系统时延飙升,请求大量堆积 | ||
中间件监控异常 | KAFKA消息堆积飙升,异步请求堆积 | |
REDIS内存使用率飙升,指标异常 | ||
ETCD连接数飙升,请求处理异常 | ||
系统依赖服务异常 | 基础依赖性服务异常 | 网关服务异常,无法接收请求 |
负载均衡服务异常,无法接收请求 | ||
VPC服务异常,无法转发请求 | ||
DNS解析服务异常,无法转发请求 | ||
逻辑依赖性服务异常 | 鉴权服务异常,鉴权失败 | |
日志服务异常,无法存取日志 | ||
容器服务异常,系统异常 | ||
对象存储服务异常,系统异常 | ||
底层硬件资源异常 | 网络中断、丢包、时延突增 | |
机房因不可控因素受损,系统异常 | ||
节点故障,系统异常 | ||
变更引起 | 软件版本变更 | 引入bug,功能不兼容 |
部署架构变更 | 引入bug,功能不兼容 | |
配置参数变更 | 引入bug,功能不兼容 | |
依赖服务变更 | 引入bug,功能不兼容 |
表1 FunctionGraph常见问题总结
针对这些问题,我们总结了如下几类通用的治理办法。
为了解决表1出现的问题,FunctionGraph在架构容灾、流控、重试、缓存、灰度升级、监控告警、管理流程上等多方面做了优化,可用性大幅提升。下面主要介绍一些FunctionGraph面向异常的设计实践,在弹性能力、系统功能等暂不展开。
实现华为云容灾1.1架构(例:服务AZ级故障域、集群跨AZ自愈能力、AZ级服务依赖隔离),FunctionGraph管理面和数据面集群部署多套,每套集群AZ隔离,实现同region内的AZ容灾。如图2所示,FunctionGraph部署多套数据面集群(承担FunctionGraph函数运行业务)和dispatcher调度集群(承担FunctionGraph的流量集群调度任务),用来提升系容量以及容灾。当前其中某个元戎集群异常时,dispatcher调度组件能及时摘除故障集群,并将流量分发至其他几个集群。
图2 FunctionGraph简略架构图
这个策略是逻辑多租服务设计的关键,需要解决无中心化后,组件扩缩容后的重均衡问题。
FunctionGraph上的客户函数流量最终达到runtime运行时之前,会经过多个链路,每个链路都有可能出现超过其承载阈值的流量。因此,为了确保各个链路的稳定性,FunctionGraph在每条链路上,防御性的追加了不同的流控策略。基本原则解决计算(cpu)、存储(磁盘、磁盘I/0)、网络(http连接、带宽)上的函数粒度的资源隔离。
函数流量从客户侧触发,最终运行起来的链路流控如图3所示。
图3 FunctionGraph流控
APIG是FunctionGraph的流量入口,支持Region级别总的流量控制,可以根据region的业务繁忙程度进行弹性扩容。同时APIG支持客户级别的流量控制,当检测到客户流量异常时,可以快速通过APIG侧限制客户流量,减少个别客户对系统稳定性的影响。
2.系统业务流控
客户流量通过APIG后,走到FunctionGraph的系统侧。基于APIG流控失效的场景,FunctionGraph构建了自身的流控策略。当前支持节点级别流控、客户api总流控、函数级别流控。当客户流量超过FunctionGraph的承载能力时,系统直接拒绝,并返回429给客户。
FunctionGraph是逻辑多租服务,控制面和数据面的资源是客户共享的,当非法客户恶意攻击时,会造成系统不稳定。FunctionGraph针对共享资源实现基于请求并发数的客户流控,严格限制客户可用的资源。另外对共享资源的资源池化来保证共享资源的总量可控制,进而保证系统的可用性。例如:http连接池、内存池、协程池。
流控属于防御式设计思想,通过提前封堵的方式减少系统过载的风险。客户正常业务突发上量需要大量的资源时,首先应该解决的是资源弹性问题,保证客户业务成功的前提下,通过流控策略兜底系统出现异常,防止爆炸面扩散。FunctionGraph支持集群节点快速弹性、支持客户函数实例快速弹性、支持客户函数实例的智能预测弹性等多种弹性能力,保证客户业务突增时依然能正常使用FunctionGraph。
FunctionGraph通过设计恰当好处的重试策略,使系统在发生异常的时候,也可以保障客户的请求最终执行成功。如图4所示,重试的策略一定要有终止条件,否则会造成重试风暴,更轻松的击穿系统的承载上限。
图4 重试策略
缓存不仅可以加速数据的访问,而且当依赖的服务故障时,仍然可以使用缓存数据,保障系统的可用性。从功能类别划分,FunctionGraph需要进行缓存的组件有两类,1是中间件,2是依赖的云服务,系统优先访问缓存数据,同时定期从中间件和依赖的云服务刷新本地缓存数据。方式如图5所示。
图5 FunctionGraph的缓存措施
上面的种种措施,可以保障客户业务平稳运行,但当客户业务出现异常一直无法恢复或者有恶意客户持续攻击FunctionGraph平台,系统资源会一直浪费在异常流量上,挤占正常客户的资源,同时系统可能会在持续高负荷运行异常流量后出现不可预期的错误。针对这种场景,FunctionGraph基于函数调用量模型构建了自身的断路器策略。具体如图6所示,根据调用量的失败率进行多级熔断,保证客户业务的平滑以及系统的稳定。
图6 熔断策略模型
逻辑多租服务,一旦升级出问题,造成的影响不可控。FunctionGraph支持按ring环升级(根据region上业务的风险度进行划分)、蓝绿发布、金丝雀发布策略,升级动作简要描述成三个步骤:
当FunctionGraph出现系统无法兜住的错误后,我们给出的解决措施就是构建监控告警能力,快速发现异常点,在分钟级别恢复故障,最大程度减少系统的中断时间。作为系统高可用的最后一道防线,快速发现问题的能力至关重要,FunctionGraph围绕着业务关键路径,构建了多个告警点。如表2所示。
监控告警 | 一级分类 | 二级分类 | 三级分类 |
依赖服务监控 | 中间件负载 | kafka负载 | 消息堆积量 |
broker磁盘使用率 | |||
redis负载 | 内存使用率 | ||
cpu使用率 | |||
依赖服务状态 | 中间件状态 | kafka连通性 | |
redis连通性 | |||
etcd连通性 | |||
云服务状态 | 认证服务连通性 | ||
对象存储连通性 | |||
日志服务连通性 | |||
…… | |||
系统服务监控 | 底层资源状态 | 集群状态 | cpu负载 |
内存负载 | |||
集群健康状态 | |||
节点状态 | cpu负载 | ||
内存负载 | |||
节点健康状态 | |||
公网流量负载 | 流量过大告警 | ||
服务进程状态 | 进程实时负载 | cpu负载 | |
内存负载 | |||
进程健康状态 | 进程异常告警 | ||
业务指标监控 | 系统可用性监控 | 拨测用例 | 用例失败告警 |
系统SLI执行成功率 | SLI下降告警 | ||
客户业务状态 | 失败告警 | ||
系统时延 | 时延增大告警 |
表2: FunctionGraph构建的监控告警
上面的一些措施从技术设计层面解决系统可用性的问题,FunctionGraph从流程上也形成了一套规章制度,当技术短期无法解决问题后,可以通过人为介入快速消除风险。具体有如下团队运作规范:
业界最先进的云服务,对外也无法承诺100%的SLA。所以,当系统自身甚至人力介入都无法在急短时间内快速恢复系统状态,这时候和客户共同设计的容灾方案就显得至关重要。一般,FunctionGraph会和客户一同设计客户端的容灾方案,当系统持续出现异常,客户端需要针对返回进行重试,当失败次数达到一定程度,需要考虑在客户端侧触发熔断,限制对下游系统的访问,同时及时切换到逃生方案。
FunctionGraph在做高可用设计时,整体遵循如下原则“冗余+故障转移”,在满足业务基本需求的情况下,保证系统稳定后在逐步完善架构。
“冗余+故障转移”包括以下能力:
容灾架构:多集群模式、主备模式
过载保护:流控、异步削峰、资源池化
故障治理:重试、缓存、隔离、降级、熔断
灰度发布:灰度切流、优雅退出
客户端容灾:重试、熔断、逃生
未来,FunctionGraph会持续从系统设计、监控、流程几个维度持续构建更高可用的服务。如图7所示,通过构建监测能力快速发现问题,通过可靠性设计快速解决问题,通过流程规范来减少问题,持续提升系统的可用性能力,为客户提供SLA更高的服务。
图7: FunctionGraph高可用迭代实践
参考文献
[1]高可用定义:https://zh.wikipedia.org/zh-hans/%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7
[2]SLA定义:https://zh.wikipedia.org/zh-hans/%E6%9C%8D%E5%8A%A1%E7%BA%A7%E5%88%AB%E5%8D%8F%E8%AE%AE
作者:安 校稿:旧浪、闻若
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。