华为云FunctionGraph构建高可用系统的实践

举报
华为云PaaS服务小智 发表于 2024/04/26 09:44:14 2024/04/26
【摘要】 本文将基于华为云FunctionGraph自身的实践,详细介绍如何构建高可用的Serverless计算平台,实现客户和平台双赢。

导语

每年,网上都会报道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常见问题总结


针对这些问题,我们总结了如下几类通用的治理办法。

  • 流量突变治理:过载保护+弹性扩缩容+熔断+异步削峰+监控告警,基于防御式的设计思想,通过过载保护+熔断确保系统所有资源受控,然后在此基础上通过提供极致的扩容能力来满足大流量,合适的客户场景推荐异步削峰来减缓系统压力,监控告警用来及时发现过载问题。
  • 系统服务异常治理:容灾架构+重试+隔离+监控告警,通过容灾架构避免系统整个宕机,通过重试来减少系统异常对客户业务的影响,通过隔离快速剥离系统异常点,防止故障扩散,通过监控告警快速发现系统服务异常问题。
  • 系统依赖服务异常治理:容灾架构+缓存降级+监控告警,通过容灾架构减少依赖服务单点故障,通过缓存降级确保依赖服务故障后系统仍能正常运行,通过监控告警快速发现依赖服务异常问题。
  • 变更引起治理:灰度升级+流程管控+监控告警,通过灰度升级避免正式客户由于系统升级异常而造成的全局故障,通过流程管控将人为变更的风险降到最低,通过监控告警快速发现变更后的故障。


FunctionGraph系统设计实践

为了解决表1出现的问题,FunctionGraph在架构容灾、流控、重试、缓存、灰度升级、监控告警、管理流程上等多方面做了优化,可用性大幅提升。下面主要介绍一些FunctionGraph面向异常的设计实践,在弹性能力、系统功能等暂不展开。

  • 容灾架构

实现华为云容灾1.1架构(例:服务AZ级故障域、集群跨AZ自愈能力、AZ级服务依赖隔离),FunctionGraph管理面和数据面集群部署多套,每套集群AZ隔离,实现同region内的AZ容灾。如图2所示,FunctionGraph部署多套数据面集群(承担FunctionGraph函数运行业务)和dispatcher调度集群(承担FunctionGraph的流量集群调度任务),用来提升系容量以及容灾。当前其中某个元戎集群异常时,dispatcher调度组件能及时摘除故障集群,并将流量分发至其他几个集群。

2 FunctionGraph简略架构图


  • 分布式无中心化架构设计,支持灵活的横向扩缩容

这个策略是逻辑多租服务设计的关键,需要解决无中心化后,组件扩缩容后的重均衡问题。

  1. 静态数据管理的无中心化:逻辑多租服务的元数据,初期由于量少,可以全部存储到同一套中间件中。随着客户上量,需要设计数据的拆分方案,支持数据的分片,应对后续海量数据读写,以及可靠性压力。
  2. 流量调度功能的无中心化:组件功能设计,支持无中心化(常见中心化依赖:锁、流控值、调度任务等),流量上量后,可扩展组件副本数量,组件通过自均衡策略,完成流量的重新负载。
  • 多维度的流控策略

FunctionGraph上的客户函数流量最终达到runtime运行时之前,会经过多个链路,每个链路都有可能出现超过其承载阈值的流量。因此,为了确保各个链路的稳定性,FunctionGraph在每条链路上,防御性的追加了不同的流控策略。基本原则解决计算(cpu)、存储(磁盘、磁盘I/0)、网络(http连接、带宽)上的函数粒度的资源隔离。

函数流量从客户侧触发,最终运行起来的链路流控如图3所示。

3 FunctionGraph流控


  1. 网关APIG流控

APIG是FunctionGraph的流量入口,支持Region级别总的流量控制,可以根据region的业务繁忙程度进行弹性扩容。同时APIG支持客户级别的流量控制,当检测到客户流量异常时,可以快速通过APIG侧限制客户流量,减少个别客户对系统稳定性的影响。

     2.系统业务流控

    • 针对api级别的流控

客户流量通过APIG后,走到FunctionGraph的系统侧。基于APIG流控失效的场景,FunctionGraph构建了自身的流控策略。当前支持节点级别流控、客户api总流控、函数级别流控。当客户流量超过FunctionGraph的承载能力时,系统直接拒绝,并返回429给客户。

  • 系统资源流控

FunctionGraph是逻辑多租服务,控制面和数据面的资源是客户共享的,当非法客户恶意攻击时,会造成系统不稳定。FunctionGraph针对共享资源实现基于请求并发数的客户流控,严格限制客户可用的资源。另外对共享资源的资源池化来保证共享资源的总量可控制,进而保证系统的可用性。例如:http连接池、内存池、协程池。

  • 并发数控制:构建基于请求并发数的FunctionGraph函数粒度的流控策略,FunctionGraph的客户函数执行时间有毫秒、秒、分钟、小时等多种类型,常规的QPS每秒请求数的流控策略在处理超长执行的请求时有先天不足,无法限制同一时刻客户占用的系统共享资源。基于并发数的控制策略,严格限制了同一时刻的请求量,超过并发数直接拒绝,保护系统共享资源。
  • http连接池:构建高并发的服务时,合理的维护http的长连接数量,能最大限度减少http连接的资源开销时间,同时保证http连接数资源的可控,确保系统安全性的同时提升系统性能。业界可以参考http2的连接复用,以及fasthttp内部的连接池实现,其原理都是尽量减少http的数量,复用已有的资源。
  • 内存池:客户的请求和响应报文特别大,同时并发特别高的场景下,单位时间占用系统的内存较大,当超过阈值后,会轻松造成系统内存溢出,导致系统重启。基于此场景,FunctionGraph新增了内存池的统一控制,在请求入口和响应出口,校验客户请求报文是否超过阈值,保护系统内存可控。
  • 协程池:FunctionGraph构建于云原生平台上,采用的go语言。如果每一个请求都使用一个协程来进行日志和指标的处理,大并发请求来临时,导致有海量的协程在并发执行,造成系统的整体性能大幅下降。FunctionGraph引入go的协程池,通过将日志和指标的处理任务改造成一个个的job任务,提交到协程池中,然协程池统一处理,大幅缓解了协程爆炸的问题。
  • 异步消费速率控制:异步函数调用时,会优先放到FunctionGraphkafka中,通过合理设置客户的kafka消费速率,确保函数实例始终够用,同时防止过量的函数调用,导致底层资源被迅速耗光。
  1. 函数实例控制
    • 客户实例配额:通过限制客户总配额,防止恶意客户将底层资源耗光,来保障系统的稳定性。当客户业务确实有需要,可以通过申请工单的方式快速扩充客户配额。
    • 函数实例配额:通过限制函数配额,防止单个客户的函数将客户的实例耗光,同时也能防止客户配额失效,短时间内造成大量的资源消耗。另外,客户业务如果涉及数据库、redis等中间件的使用,通过函数实例配额限制,可以保护客户的中间件连接数在可控范围内。
  2. 高效的资源弹性能力

流控属于防御式设计思想,通过提前封堵的方式减少系统过载的风险。客户正常业务突发上量需要大量的资源时,首先应该解决的是资源弹性问题,保证客户业务成功的前提下,通过流控策略兜底系统出现异常,防止爆炸面扩散。FunctionGraph支持集群节点快速弹性、支持客户函数实例快速弹性、支持客户函数实例的智能预测弹性等多种弹性能力,保证客户业务突增时依然能正常使用FunctionGraph

  • 重试策略

FunctionGraph通过设计恰当好处的重试策略,使系统在发生异常的时候,也可以保障客户的请求最终执行成功。如图4所示,重试的策略一定要有终止条件,否则会造成重试风暴,更轻松的击穿系统的承载上限。

                                    图重试策略

  1. 函数请求失败重试
    • 同步请求:当客户请求执行时,遇到系统错误时,FunctionGraph会将请求转发至其他集群,最多重试3次,确保客户的请求,在遇到偶现的集群异常,也可以在其他集群执行成功。
    • 异步请求:由于异步函数对实时性要求不高,客户函数执行失败后,系统可以针对失败请求做更为精细的重试策略。当前FunctionGraph支持二进制指数退避的重试,当函数由于系统错误异常终止后,函数会按2,4,8,16指数退避的方法,当间隔退避到20分钟时,后续重试均按照20分的间隔进行,函数请求重试时间最大支持6小时,当超过后,会按失败请求处理,返回给客户。通过二进制指数退避的方式,可以最大程度保障客户业务的稳定性。
  2. 依赖服务间的重试
  • 中间件的重试机制:以redis为例,当系统读写redis偶现失败时,会sleep一段时间,再重复执行redis的读写操作,最大重试次数3次。
  • http请求重试机制:当http请求由于网络波动,发生eofio timeout之类的错误时,会sleep一段时间,在重复http的发送操作,最大重试次数3次。
  • 缓存

缓存不仅可以加速数据的访问,而且当依赖的服务故障时,仍然可以使用缓存数据,保障系统的可用性。从功能类别划分,FunctionGraph需要进行缓存的组件有两类,1是中间件,2是依赖的云服务,系统优先访问缓存数据,同时定期从中间件和依赖的云服务刷新本地缓存数据。方式如图5所示。

  1. 缓存中间件数据:FunctionGraph通过发布订阅的方式,监听中间件数据的变化及时更新到本地缓存,当中间件异常时,本地缓存可以继续使用,维持系统的稳定性。
  2. 缓存关键依赖服务数据:以华为云的身份认证服务IAM为例,FunctionGraph会强依赖IAM,当客户发起首次请求,系统会将token缓存到本地,过期时间24小时,当IAM挂掉后,不影响老的请求。FunctionGraph系统的使用。其他关键的云服务依赖做法一直,都是把关键的数据临时缓存到本地内存。

5  FunctionGraph的缓存措施

  • 熔断

上面的种种措施,可以保障客户业务平稳运行,但当客户业务出现异常一直无法恢复或者有恶意客户持续攻击FunctionGraph平台,系统资源会一直浪费在异常流量上,挤占正常客户的资源,同时系统可能会在持续高负荷运行异常流量后出现不可预期的错误。针对这种场景,FunctionGraph基于函数调用量模型构建了自身的断路器策略。具体如图6所示,根据调用量的失败率进行多级熔断,保证客户业务的平滑以及系统的稳定。

6 熔断策略模型

  • 隔离
    1. 异步函数业务隔离:按照异步请求的类别,FunctionGraphKafka的消费组划分为定时触发器消费组、专享消费组、通用消费组、异步消息重试消费组,topic同理也划分为对等类别。通过细分consumer消费组和topic,定时触发器业务和大流量业务隔离,正常业务和重试请求业务隔离,客户的业务请求得到最高优先级的保障。
    2. 安全容器隔离:传统cce容器基于cgroup进行隔离,当客户增多,客户调用量变大时,会偶现客户间的互相干扰。通过安全容器可以做到虚拟机级别的隔离,客户业务互不干扰。
  • 灰度升级

逻辑多租服务,一旦升级出问题,造成的影响不可控。FunctionGraph支持按ring环升级(根据region上业务的风险度进行划分)、蓝绿发布、金丝雀发布策略,升级动作简要描述成三个步骤:

  1. 升级前集群的流量隔离:当前FunctionGraph升级时,优先将升级集群的流量隔离,确保新流量不在进入升级集群;
  2. 升级前集群的流量迁移、优雅退出:将流量迁移到其他集群,同时升级集群的请求彻底优雅退出后,执行升级操作;
  3. 升级后的集群支持流量按客户迁入:升级完成后,将拨测客户的流量转发到升级集群,待拨测用例全部执行成功后,在将正式客户的流量迁进来。
  • 监控告警

FunctionGraph出现系统无法兜住的错误后,我们给出的解决措施就是构建监控告警能力,快速发现异常点,在分钟级别恢复故障,最大程度减少系统的中断时间。作为系统高可用的最后一道防线,快速发现问题的能力至关重要,FunctionGraph围绕着业务关键路径,构建了多个告警点。如表2所示。

监控告警

一级分类

二级分类

三级分类

依赖服务监控

中间件负载

kafka负载

消息堆积量

broker磁盘使用率

redis负载

内存使用率

cpu使用率

依赖服务状态

中间件状态

kafka连通性

redis连通性

etcd连通性

云服务状态

认证服务连通性

对象存储连通性

日志服务连通性

……

系统服务监控

底层资源状态

集群状态

cpu负载

内存负载

集群健康状态

节点状态

cpu负载

内存负载

节点健康状态

公网流量负载

流量过大告警

服务进程状态

进程实时负载

cpu负载

内存负载

进程健康状态

进程异常告警

业务指标监控

系统可用性监控

拨测用例

用例失败告警

系统SLI执行成功率

SLI下降告警

客户业务状态

失败告警

系统时延

时延增大告警

2 FunctionGraph构建的监控告警

  • 流程规范

上面的一些措施从技术设计层面解决系统可用性的问题,FunctionGraph从流程上也形成了一套规章制度,当技术短期无法解决问题后,可以通过人为介入快速消除风险。具体有如下团队运作规范:

  1. 内部war room流程:遇到现网紧急问题,团队内部快速组织起关键角色,第一时间恢复现网故障;
  2. 内部变更评审流程:系统版本在测试环境浸泡验证没问题后,在正式变更现网前,需要编写变更指导书,识别变更功能点和风险点,经团队关键角色评估后,才准许上现网,通过标准的流程管理减少人为变更导致异常;
  3. 定期现网问题分析复盘:例行每周现网风险评估、告警分析复盘,通过问题看系统设计的不足之处,举一反三,优化系统。
  • 客户端容灾

业界最先进的云服务,对外也无法承诺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

  

作者:安    校稿:旧浪、闻若

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。