Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >B站高可用用架构实践

B站高可用用架构实践

原创
作者头像
腾讯云开发者
发布于 2020-04-22 10:31:13
发布于 2020-04-22 10:31:13
241.1K96
举报

流量洪峰下要做好高服务质量的架构是一件具备挑战的事情,本文是B站技术总监毛剑老师在「腾讯云开发者社区沙龙online」的分享整理,详细阐述了从Google SRE的系统方法论以及实际业务的应对过程中出发,一些体系化的可用性设计。对我们了解系统的全貌、上下游的联防有更进一步的帮助。

一、负载均衡

负载均衡具体分成两个方向,一个是前端负载均衡,另一个是数据中心内部的负载均衡。

前端负载均衡方面,一般而言用户流量访问层面主要依据DNS,希望做到最小化用户请求延迟。将用户流量最优地分布在多个网络链路上、多个数据中心、多台服务器上,通过动态CDN的方案达到最小延迟。

以上图为例,用户流量会先流入BFE的前端接入层,第一层的BFE实际上起到一个路由的作用,尽可能选择跟接入节点比较近的一个机房,用来加速用户请求。然后通过API网关转发到下游的服务层,可能是内部的一些微服务或者业务的聚合层等,最终构成一个完整的流量模式。

基于此,前端服务器的负载均衡主要考虑几个逻辑:

  • 第一,尽量选择最近节点;
  • 第二,基于带宽策略调度选择API进入机房;
  • 第三,基于可用服务容量平衡流量。

数据中心内部的负载均衡方面,理想情况下会像上图右边显示那样,最忙和最不忙的节点所消耗的CPU相差幅度较小。但如果负载均衡没做好,情况可能就像上图左边一样相差甚远。由此可能导致资源调度、编排的困难,无法合理分配容器资源。

因此,数据中心内部负载均衡主要考虑:

  • 均衡流量分发;
  • 可靠识别异常节点;
  • scale-out,增加同质节点以扩容;
  • 减少错误,提高可用性。

我们此前通过同质节点来扩容就发现,内网服务出现CPU占用率过高的异常,通过排查发现背后RPC点到点通信间的 health check 成本过高,产生了一些问题。另外一方面,底层的服务如果只有单套集群,当出现抖动的时候故障面会比较大,因此需要引入多集群来解决问题。

通过实现 client 到 backend 的子集连接,我们做到了将后端平均分配给客户端,同时可以处理节点变更,持续不断均衡连接,避免大幅变动。多集群下,则需要考虑集群迁移的运维成本,同时集群之间业务的数据存在较小的交集。

回到CPU忙时、闲时占用率过大的问题,我们会发现这背后跟负载均衡算法有关。

第一个问题,对于每一个qps,实际上就是每一个query、查询、API请求,它们的成本是不同的。节点与节点之间差异非常大,即便你做了均衡的流量分发,但是从负载的角度来看,实际上还是不均匀的。

第二个问题,存在物理机环境上的差异。因为我们通常都是分年采购服务器,新买的服务器通常主频CPU会更强一些,所以服务器本质上很难做到强同质。

基于此,参考JSQ(最闲轮训)负载均衡算法带来的问题,发现缺乏的是服务端全局视图,因此我们的目标需要综合考虑负载和可用性。我们参考了《The power of two choices in randomized load balancing》的思路,使用the choice-of-2算法,随机选取的两个节点进行打分,选择更优的节点:

  • 选择backend:CPU,client:health、inflight、latency作为指标,使用一个简单的线性方程进行打分;
  • 对新启动的节点使用常量惩罚值(penalty),以及使用探针方式最小化放量,进行预热;
  • 打分比较低的节点,避免进入“永久黑名单”而无法恢复,使用统计衰减的方式,让节点指标逐渐恢复到初始状态(即默认值)。

通过优化负载均衡算法以后,我们做到了比较好的收益。

二、限流

避免过载,是负载均衡的一个重要目标。随着压力增加,无论负载均衡策略如何高效,系统某个部分总会过载。我们优先考虑优雅降级,返回低质量的结果,提供有损服务。在最差的情况,妥善的限流来保证服务本身稳定。

限流这块,我们认为主要关注以下几点:

  • 一是针对qps的限制,带来请求成本不同、静态阈值难以配置的问题;
  • 二是根据API的重要性,按照优先级丢弃;
  • 三是给每个用户设置限制,全局过载发生时候,针对某些“异常”进行控制非常关键;
  • 四是拒绝请求也需要成本;
  • 五是每个服务都配置限流带来的运维成本。

在限流策略上,我们首先采用的是分布式限流。我们通过实现一个quota-server,用于给backend针对每个client进行控制,即backend需要请求quota-server获取quota。

这样做的好处是减少请求Server的频次,获取完以后直接本地消费。算法层面使用最大最小公平算法,解决某个大消耗者导致的饥饿。

在客户端侧,当出现某个用户超过资源配额时,后端任务会快速拒绝请求,返回“配额不足”的错误,有可能后端忙着不停发送拒绝请求,导致过载和依赖的资源出现大量错误,处于对下游的保护两种状况,我们选择在client侧直接进行流量,而不发送到网络层。

我们在Google SRE里学到了一个有意思的公式,max(0, (requests- K*accepts) / (requests + 1))。通过这种公式,我们可以让client直接发送请求,一旦超过限制,按照概率进行截流。

在过载保护方面,核心思路就是在服务过载时,丢弃一定的流量,保证系统临近过载时的峰值流量,以求自保护。常见的做法有基于CPU、内存使用量来进行流量丢弃;使用队列进行管理;可控延迟算法:CoDel 等。

简单来说,当我们的CPU达到80%的时候,这个时候可以认为它接近过载,如果这个时候的吞吐达到100,瞬时值的请求是110,我就可以丢掉这10个流量,这种情况下服务就可以进行自保护,我们基于这样的思路最终实现了一个过载保护的算法。 

我们使用CPU的滑动均值(CPU > 800 )作为启发阈值,一旦触发就进入到过载保护阶段。算法为:(MaxPass * AvgRT) < InFlight。其中MaxPass、AvgRT都为触发前的滑动时间窗口的统计值。

限流效果生效后,CPU会在临界值(800)附近抖动,如果不使用冷却时间,那么一个短时间的CPU下降就可能导致大量请求被放行,严重时会打满CPU。在冷却时间后,重新判断阈值(CPU > 800 ),是否持续进入过载保护。

三、重试

流量的走向,一般会从BFE到SLB然后经过API网关再到BFF、微服务最后到数据库,这个过程要经过非常多层。在我们的日常工作中,当请求返回错误,对于backend部分节点过载的情况下,我们应该怎么做?

  • 首先我们需要限制重试的次数,以及基于重试分布的策略;
  • 其次,我们只应该在失败层进行重试,当重试仍然失败时,我们需要全局约定错误码,避免级联重试;
  • 此外,我们需要使用随机化、指数型递增的充实周期,这里可以参考Exponential Backoff和Jitter;
  • 最后,我们需要设定重试速率指标,用于诊断故障。

而在客户端侧,则需要做限速。因为用户总是会频繁尝试去访问一个不可达的服务,因此客户端需要限制请求频次,可以通过接口级别的error_details,挂载到每个API返回的响应里。

四、超时

我们之前讲过,大部分的故障都是因为超时控制不合理导致的。首当其冲的是高并发下的高延迟服务,导致client堆积,引发线程阻塞,此时上游流量不断涌入,最终引发故障。所以,从本质上理解超时它实际就是一种Fail Fast的策略,就是让我们的请求尽可能消耗,类似这种堆积的请求基本上就是丢弃掉或者消耗掉。

另一个方面,当上游超时已经返回给用户后,下游可能还在执行,这就会引发资源浪费的问题。

再一个问题,当我们对下游服务进行调优时,到底如何配置超时,默认值策略应该如何设定?生产环境下经常会遇到手抖或者错误配置导致配置失败、出现故障的问题。所以我们最好是在框架层面做一些防御性的编程,让它尽可能让取在一个合理的区间内。 

进程内的超时控制,关键要看一个请求在每个阶段(网络请求)开始前,检查是否还有足够的剩余来处理请求。另外,在进程内可能会有一些逻辑计算,我们通常认为这种时间比较少,所以一般不做控制。

现在很多RPC框架都在做跨进程超时控制,为什么要做这个?跨进程超时控制同样可以参考进程内的超时控制思路,通过RPC的源数据传递,把它带到下游服务,然后利用配额继续传递,最终使得上下游链路不超过一秒。

五、应对连锁故障

结合我们上面讲到的四个方面,应对连锁故障,我们有以下几大关键点需要考虑。

第一,我们需要尽可能避免过载。因为节点一个接一个挂了的话,最终服务会雪崩,有可能机群都会跟着宕掉,所以我们才提到要做自保护。

第二,我们通过一些手段去做限流。它可以让某一个client对服务出现高流量并发请求时进行管控,这样的话服务也不容易死。另外,当我们无法正常服务的时候,还可以做有损服务,牺牲掉一些非核心服务去保证关键服务,做到优雅降级。

第三,在重试策略上,在微服务内尽可能做退避,尽可能要考虑到重试放大的流量倍数对下游的冲击。另外还要考虑在移动端用户用不了某个功能的情况下,通常会频繁刷新页面,这样产生的流量冲击,我们在移动端也要进行配合来做流控。

第四,超时控制强调两个点,进程内的超时和跨进程的传递。最终它的超时链路是由最上层的一个节点决定的,只要这一点做到了,我觉得大概率是不太可能出现连锁故障的。 

第五,变更管理。我们通常情况下发布都是因为一些变更导致的,所以说我们在变更管理上还是要加强,变更流程中出现的破坏性行为应该要进行惩罚,尽管是对事不对人,但是还是要进行惩罚以引起重视。

第六,极限压测和故障演练。在做压测的时候,可能压到报错就停了。我建议最好是在报错的情况下,仍然要继续加压,看你的服务到底是一个什么表现?它能不能在过载的情况下提供服务?在上了过载保护算法以后,继续加压,积极拒绝,然后结合熔断的话,可以产生一个立体的保护效果。 经常做故障演练可以产生一个品控手册,每个人都可以学习,经常演练不容易慌乱,当在生产环境中真的出现问题时也可以快速投入解决。

第七,考虑扩容、重启、消除有害流量。

如上图所示的参考,就是对以上几个策略的经典补充,也是解决各种服务问题的玄学

「腾讯云开发者社区」公众号回复「在线沙龙」获取PPT下载链接~

六、Q&A

Q:请问负载均衡依据的 Metric是什么?

A:我们用服务端的话,主要是用CPU,我觉得CPU是最能体现的。从客户端角度,我是用的健康度,健康度指的是连接的成功率。延迟也是一个很重要的指标,另外我们要考虑到每一个client往不同的back end发了多少个请求。

Q:BFE到SLB是走公网还是专线?

A:这个其实有公网也有专线。

Q:如果client就几千量级,每10s pingpong 一下,其实也就几百 qps?会造成蛮高的cpu开销?

A:如果你的client是几千,但上游你的各种服务加起来client实际上是非常多的可能过万。 所以它是会造成蛮高的CPU开销的,因为好多个不同的应用来healthcheck,其实这个量就非常大了。

Q:多集群的成本是怎么考虑的?

A:分集群。前文提到的多集群更多是在同一个机房内布置多套机群,那么这个多套集群,首先它肯定资源是冗余和翻倍的。 这个确实是需要一定成本,所以我们也不是所有服务都会来做这种冗余,只会针对核心服务。所以本质上就是花些钱,做些冗余,来尽可能提升我们的可用性,因为你越底层的服务一旦故障,它的故障面真的是扩散非常大。 

Q:超时传递是不是要求太严格了,如果有一个节点出问题就不行了。

A:这个策略就是超时传递,我们默认是传递的,那么在有一些case情况下,即便超时仍然要继续运行,这个行为实际上是可以通过我们的context上下文把它覆盖掉,所以还是看你代码的逻辑处理。

Q:用户的接入节点的质量和容量是怎么平衡的?

A:取决于调度的策略。通常来讲需要先看你的服务是什么用途,如果是那种面向用户体验型的,或者功能型的,我觉得质量是优先考虑的。其次,在你转发的机房不过载的情况下,尽可能交付到最近的节点,那么极端情况下有可能你机房过载,那么这种情况下其实是不得已通过接入节点来转发到其他的核心机房。 

讲师简介

毛剑,bilibili技术总监,腾讯云最具价值专家(TVP)
毛剑,bilibili技术总监,腾讯云最具价值专家(TVP)

毛剑,bilibili技术总监,腾讯云最具价值专家(TVP)。负责bilibili数据平台部,拥有近十年的服务端研发经验。擅长高性能、高可用的服务端研发,熟悉Go、Java、C等语言。在B站参与了,从巨石架构到微服务的完整转型,包含微服务治理、微服务可用性设计,微服务数据一致性设计,微服务中间件,微服务监控,微服务日志收集,微服务负载均衡,和微服务RPC框架开发等。

开源业内比较有影响力的项目: goim https://github.com/Terry-Mao/goim 分布式IM长连接广播服务; bfs https://github.com/Terry-Mao/bfs 分布式小文件存储

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
96 条评论
热度
最新
见证社死时刻 ...
见证社死时刻 ...
回复回复1举报
打卡,感谢分享~~
打卡,感谢分享~~
回复回复点赞举报
程序员何必为难程序员 纵观历史 谁都有过头疼的时刻
程序员何必为难程序员 纵观历史 谁都有过头疼的时刻
回复回复点赞举报
看这么多评论,你们运营部要加薪么
看这么多评论,你们运营部要加薪么
回复回复点赞举报
慕名而来
慕名而来
回复回复点赞举报
打卡
打卡
回复回复点赞举报
大卡
大卡
回复回复点赞举报
奥利给
奥利给
回复回复点赞举报
全网呼叫蒙古上单
全网呼叫蒙古上单
22点赞举报
跟我们内蒙古有关系么
跟我们内蒙古有关系么
回复回复点赞举报
哈哈哈哈
哈哈哈哈
回复回复点赞举报
来打个卡...
来打个卡...
回复回复点赞举报
加载更多
推荐阅读
编辑精选文章
换一批
程序员从幼稚到成熟的标志是什么?
作为一个在编程界摸爬滚打多年的老鸟,今天我想和大家聊聊咱们程序员成长的那些事儿。我们都知道,这条路可不简单,但每一步都特别关键。
伍六七AI编程
2024/08/20
910
程序员从幼稚到成熟的标志是什么?
k8s: 到底谁才是草台班子?
大家在对 2023 年诸多互联网公司故障的总结中多次提到了控制 “爆炸半径”,几乎都在说缩小集群规模,那除了缩小集群规模外还有没有其他办法呢?如果一出问题就通过缩小规模去解决,多少会显得有点不够专业(草台班子)。k8s 已经经历了九年半的发展,众多的终端用户在以什么样的方式使用 k8s,即便社区高手如云,也很难把所有使用场景都考虑到并且处理好,但也不至于差到连我们这群"草台班子"都能想到的一些最基本的问题(比如控制爆炸半径)都想不到。比起把集群搞大出问题的人,反而是在出问题后只会喊控制集群规模的那些 k8s 相关的云原生专家们,那些 k8s 集群管理员们,更像是草台班子。(并没有说 k8s 等于云原生的意思,但只要做的事情和 k8s 沾点边就号称云原生,这是事实)
李鹤
2024/01/07
4660
多云容器编排 Karmada-Operator 实践
Karmada作为开源的云原生多云容器编排项目,吸引了众多企业共同参与项目开发,并运行于生产环境中。同时多云也逐步成为数据中心建设的基础架构,多区域容灾与多活、大规模多集群管理、跨云弹性与迁移等场景推动云原生多云相关技术的快速发展。
2020labs小助手
2022/09/29
9560
云原生实践总结
CLOUD NATIVE LANDSCAPE https://cncf.landscape2.io/?group=projects-and-products
SRE运维进阶之路
2024/04/23
1900
云原生实践总结
Kubernetes多集群管理之路
随着Kubernetes在企业中的应用愈发广泛、普及,越来越多的公司开始在生产环境中运维多个Kubernetes集群。本文主要讲述了一些对于Kubernetes多集群管理的思考,包括为什么需要多集群、多集群的优势以及现有的一些基于Kubernetes衍生出的多集群管理架构。
CNCF
2022/11/28
1.9K0
Kubernetes多集群管理之路
节点运维新范式,原生节点助力企业全链路降本
在云原生领域,Serverless 已然是大势所趋。相比 Serverful 模式(基于云服务器集群的K8s运维模式),Serverless 模式屏蔽了资源概念,大幅提升运维效率。用户无需介入底层运维:像操作系统的安全补丁升级这样的动作,判断升级时机 - 升级前置检查 - 无损分批升级全部都由平台自动闭环。但 Serverless 真的适合所有场景么?其实不然。
腾讯云原生
2022/11/25
8370
小红书近线服务统一调度平台建设实践
随着公司的发展,技术架构逐步演进为在线、近线、离线三位一体架构。近线服务介于在线和离线之间,一般采用异步计算的方式,并不要求立即返回结果,但是计算的执行却和在线服务类似。容器架构团队设计了一套基于容器的近线服务统一调度平台,支持数十万核近线服务接近0计算成本运行。
用户6543014
2023/03/02
8600
小红书近线服务统一调度平台建设实践
多集群编排很难很繁琐?一定是你没用对管理系统
云原生技术的不断普及,不仅让使用Kubernetes部署应用成为了当下最主流的方式,而且标志着众多企业迈入了多集群时代。随着集群数量的不断增长,企业在集群管理和运维方面也迎来了诸如集群配置重复劳动、维护管理繁琐等等问题和挑战。
米开朗基杨
2021/07/15
6030
Karmada: 云原生多云容器编排平台
7月17日,在Cloud Native Days China云原生多云多集群专场,华为云原生开源负责人王泽锋发表了《Karmada: 云原生多云容器编排平台》主题演讲,分享了在云原生多云多集群方面的思考与实践。
崔秀龙
2021/08/12
1.4K0
Karmada: 云原生多云容器编排平台
搞定微服务线上生命周期管理,同时发布上千个服务节点不是事儿
如果只看一个服务节点的部署,貌似是一项非常简单的工作,但如果同时发布成百上千个服务节点,尤其是需要在不影响线上业务的前提下完成发布工作,就会变得比较复杂。
博文视点Broadview
2020/06/15
1.1K0
每周云安全资讯-2023年第14周
1 Microsoft修补Azure云服务中的“危险”RCE漏洞 微软修补了云托管基础设施 Azure Service Fabric 组件中的一个“危险”的缺陷。如果被利用,将允许未经身份验证的攻击者在平台托管的容器中执行恶意代码。 https://cloudsec.tencent.com/article/1kYUYT 2 K8S攻击案例:内存泄漏导致集群接管 本案例通过heapdump泄露分析内存,发现了SA Token、API Server地址,并从API Server接口中获得了ConfigMaps凭
云鼎实验室
2023/04/06
3470
每周云安全资讯-2023年第14周
K8s 多集群思考、实践和探索
把联邦的所有配置信息都写到 annotations 里,整个创建流程与 K8s 类似。配置信息先到 Federated API Server,Federated Controller 把应用创建到各子集群。
SRE运维进阶之路
2024/05/11
3110
K8s 多集群思考、实践和探索
什么是 Kubernetes
​它是一个全新的基于容器技术的分布式架构领先方案,确切地说,Kubernetes是谷歌严格保密十几年的秘密武器Borg的一个开源版本。Borg是谷歌内部使用的大规模集群管理系统,它基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
星哥玩云
2022/09/15
3440
什么是 Kubernetes
对k8s的一些总结
比如大模型很热,这么马上大谈特谈大模型,似乎大模型能解决一切问题。然后网上到处去抄,把别人的模型,拿来用一下,关键抄都不会抄。问题一堆,然后骂手下无能,逼这个赶那个的。
赵云龙龙
2024/07/24
1080
对k8s的一些总结
vivo大规模 Kubernetes 集群自动化运维实践
随着vivo业务迁移到K8s的增长,我们需要将K8s部署到多个数据中心。如何高效、可靠的在数据中心管理多个大规模的K8s集群是我们面临的关键挑战。kubernetes的节点需要对OS、Docker、etcd、K8s、CNI和网络插件的安装和配置,维护这些依赖关系繁琐又容易出错。
2020labs小助手
2022/06/13
9520
推荐21-备战双 11!蚂蚁金服万级规模 K8s 集群管理系统如何设计?
导读:Kubernetes 的出现使得广大开发同学也能运维复杂的分布式系统,它大幅降低了容器化应用部署的门槛,但运维和管理一个生产级的高可用 Kubernetes 集群仍十分困难。本文将分享蚂蚁金服是如何有效可靠地管理大规模 Kubernetes 集群的,并会详细介绍集群管理系统核心组件的设计。
猿哥
2019/10/29
7.7K0
微众银行案例|容器化实践在金融行业落地面临的问题和挑战
作者陈广镇、李焕,微众银行容器平台负责人,拥有大规模 Kubernetes 集群开发运维经验。目前负责微众银行容器项目规划、容器平台架构和开发。 本文整理自微众银行容器负责人陈广镇和李焕 在 Techo 开发者大会云原生专题的分享内容——微众容器化实践。本文主要和大家介绍微众的容器化实践,具体分为三个部分:里程碑、实践之路,以及未来的规划。 微众应用容器化项目始于2018年底,我们的生产环境在私有机房上,由于基础设施的差异,容器管理系统主要走自研路线,基于开源产品定制。 2019年1月,微众上线了第一
腾讯云原生
2021/01/05
1.4K0
vivo 云原生容器探索和落地实践 | Q推荐
作者 | vivo 互联网容器团队 - Pan Liangbiao 本文根据潘良彪老师在“2022 vivo 开发者大会"现场演讲内容整理而成。vivo 互联网技术公众号后台回复【2022 VDC】获取互联网技术分会场议题相关资料。 2018 年起,vivo 以容器作为基础底座,打造了一站式云原生机器学习平台。向上支撑了算法中台,为算法工程师提供数据管理、模型训练、模型管理、模型部署等能力,为广告、推荐和搜索等业务赋能,成功为算法实现了降本、提效,让云原生和容器价值初露锋芒。基于机器学习平台的试点成果
深度学习与Python
2023/03/29
6230
vivo 云原生容器探索和落地实践 | Q推荐
工商银行十年磨砺:建成同业最大规模云计算平台,既要开源又得可控
2009 年,“双十一”的大幕首次拉开,2010 年总成交额就翻了 18 倍,到了 2011 年更是翻了近 65 倍。以“双十一”为代表的各类电商大促活动直接带动了银行交易频率和数量的大幅增加,对银行系统的弹性扩缩容等能力提出了更高的要求。
深度学习与Python
2022/11/28
9780
工商银行十年磨砺:建成同业最大规模云计算平台,既要开源又得可控
剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
Kubernetes 很火,一大批互联网公司早已领先一步,搭建起专有的 PaaS平台,传统企业们看到的 Kubernetes的趋势,亦不甘落后,在试水的道上一路狂奔……
用户1532637
2018/03/29
11.9K8
剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
推荐阅读
相关推荐
程序员从幼稚到成熟的标志是什么?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档