前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >B站多活容灾高可用建设思路

B站多活容灾高可用建设思路

作者头像
春哥大魔王
发布2023-03-22 17:22:24
1.2K0
发布2023-03-22 17:22:24
举报
B站去年713挂了,后来B站也做了复盘。

看文章可以知道这次故障,主要是因为SLB层面故障引起的,最终是通过多活进行服务的恢复。

复盘这个故障,我们可以进一步学习如何搭建一个多活的架构。

B站架构主要包括用户访问、接入层、服务层、中间件/平台、基础设施。

用户访问:也就是用户使用的多端,有APP、Web、电视等。

接入层:包含三部分,有动态CDN,三方CDN、七层SLB负载均衡、SLB下面还有一层API GW。

服务层:第一层服务是BFF网关层,网关层下面是多个业务的服务层。

中间件/平台:各种核心中间件,包括缓存、DB、可观测系统、KV、对象存储、业务流程平台等。

基础设施:包括PaaS、IaaS、混合云等。

为了实现系统的高可用,架构中每一层针对于常见的故障都做了高可用方案。

在接入层,包括了DCND、SLB、API GW。

用户基于DNS和HTTP DNS访问DCDN节点,然后DCDN回源时,由边缘POP点做流量汇聚,路由到机房。

因为B站做了多活,所以有多个可用区。

接入层这部分,可能出现的故障有网络故障、组件故障、服务故障、机房故障四种。

当用户访问DCDN节点时,运营商网络故障或CDN节点回到机房的骨干网故障都属于网络故障。

713故障就是组件层面的SLB组件故障。

服务故障一般是由于服务代码的bug或性能过载导致的。

机房故障不太常见。

对于网络故障时,比如DNS故障时,很多公司的做法是降级到HTTP DNS。

对于端上来说,HTTP请求解析到一个地区返回多个DCND节点,让客户端做一个最佳链路选择。

当APP访问DCDN时出现网络故障时,可以降级到三方CDN,实现对DCDN的容灾。

当CDN回源时,会走pop点进行流量汇聚,在pop点可以做多个线路互备。

对于组件层故障时,比如SLB故障时,SLB向后端转发时,是可以发现多个可用区服务的,包括API GW以及没走API GW的其他服务。

在单可用区故障时,可以自动降级到其他可用区节点。

当SLB代理的服务出现异常时,可以做相应的API降级、熔断、限流等。

很多能力从SLB下放到API GW了,API GW可以返回多个可用区服务节点,当出现故障时,可以自动降级到其他可用区,同时也支持API的降级、熔断、限流。

SLB是南北向的流量架构,服务层流量是东西向的流量架构,服务层的高可用方案偏向于服务治理。

在B站,服务发现是通过Discovery实现的,采用的是多可用区部署。

比如Service B在可用区A和可用区B都有部署,部署的是k8s多pod模式,分布在不同的物理机上。

在服务之间调用时,服务端会返回自己目前的cpu使用率,调用方可以分析服务响应的rt、等待的response、成功率来选择最优的server节点来动态调整路由权重。

这样即使同一个服务不同实例部署在不同算力的物理节点上,最终仍然可以实现容器层面CPU使用率的负载均衡。

B站服务是多可用性部署的,当一个可用区服务故障时,会通过服务发现来调用其他可用区的服务,如果这个服务所在的可用区都挂了,会采用内容质量降级的策略。

降级策略包括:服务降级、内容降级。

服务降级,是本来访问B服务,降级到访问C服务。

内容降级,就是将数据在本地缓存下来,当服务不可用时,从本地缓存响应服务请求。

比如B站的首页推荐功能,当推荐服务不可用时,会降级到一些热门的稿件,让用户有视频可以看,保证了不出现白屏的情况。

在服务之间调用时,经常会出现流量过载的情况,这时常用的手段就是限流了。

B站限流有两种模式:全局流控、单点动态限流。

全局限流,是分布式限流,通过服务框架层面的拦截来实现,拦截的流量是东西向的流量调用,比如HTTP、grpc、mysql数据库的限流。

单点动态限流,基于谷歌BBR拥塞控制算法实现的,基于服务单节点的cpu使用率、成功率、RT动态决定这个节点现在请求要不要处理,以自适应限流保护。

就故障次数来说,除了服务层故障之外,最多的就是中间件的故障了。

在架构中,经常采用缓存进行数据加速、读cache miss、读db。

对于写场景,一般采用MQ做异步持久化,然后由专门的Job消费消息。

如果db做了主从同步,需要解决缓存更新一致性的问题,B站采用的是,通过canal消费db binlog,将消费过来的数据写到mq,再通过Job刷新缓存。

这个架构中,关键的中间件有:缓存、MQ、DB。

架构设计原则,遵守最终一致性,因为B站业务特点上,很多场景数据一致性对于用户是没那么重要的,只需做到最终一致性就可以了。

对于缓存高可用的实现,采用了Redis Cluster、Redis、Memcache。

实现上,优先采用Redis Cluster,然后是Redis,最后是Memcache。

B站最早之前,很多服务是直连Redis Cluster的,而且每种语言都需要用自己的SDK,经常出现问题。

Redis在4.0版本是一个单线程服务模型,6.0之后引入了IO Thread多线程。

在单线程模式下,用短连接形式访问Redis,性能会下降的特别严重,单核场景,长连接能跑到10w qps,短连接的话下降近10倍,只有1~2w qps。

java SDK连接池配置有两个参数,maxtotal、maxidle。当连接数超过maxidle后,后续的链接就变成短连接了,会导致服务挂掉。

于是,后来B站建设了proxy代理模式,通过sidecar模式来部署,近两年没有出现过因为redis cluster引发的大规模故障了。

因为sidecar部署需要容器,为降低成本,今年增加了proxyless sdk部署模式。

MQ在上面的场景,主要是做数据的临时持久化和异步写DB的,是一个集中式代理部署模式,提供redis和gRPC协议的访问。

后期服务做了升级,核心服务业做了降级,可以在MQ故障时,绕过MQ实现RPC和job直接通信,实现了容灾。

MySQL层,目前有一个proxy代理、sidecar模式部署。

这种模式实现读写分离,对业务是透明的。

常用的一个功能就是sql的拦截,比如有一个慢sql出现了,导致数据库过载,可以通过Sql Proxy把这个sql做一个拦截,及时恢复数据库。

还可以实现proxy联动BRM高可用组件,当数据库的某个节点不可用时,自动感知并切换。

对于机房级别的故障,最快的容灾止损手段就是多活了。

713故障,复盘B站多活架构,发现一些问题:

  1. 多活元信息是没有平台管理的:那个业务做了多活,是什么类型的多活,是同城还是异地单元化,哪些业务支持多活,当前多活流量调用策略是什么,用户随机回到了那个机房,是基于用户ID还是设备ID做路由策略。这些信息都没有地方维护,只有文档维护,导致信息割裂严重,信息更新不及时。
  2. 多活切流依赖于CDN运维:因为B站多活流量调度是在边缘DCDN实现的,一般是SRE提出一个切流需求,告诉CDN同学,同时告知要切到哪个域名、哪个URL,然后CDN开始变更切流,同时通知SRE和研发,让SRE和研发一起观察服务状态和多机房的流量。

如果过程中,有一个接口或一个规则错了,这个流程都要再走一遍,导致当时切多活效率极差,并且容灾效果不好。

基于以上两个问题,提出了两个优化:

  1. 多活基础能力建设;
  2. 多活管控能力提升;

哪个业务做了多活,应用是什么样多活模式,多活里每个机房定位是什么,这些都属于多活元信息。

建立多活元信息,需要着手梳理业务模型和定义。

之前业务模型是三层,一层是部门,二层是项目,三层是应用。

项目代表服务组织,或服务本身,信息比较混乱,无法反映业务真实信息。

后来梳理,以业务维度做聚合,业务再向上关联时有两个视角,一个是组织视角,一个是业务域。

组织视角,是你真实的组织结构,用于权限、审批、预算、成本信息同步。

多活有几个概念,GZone、RZone、CZone。

GZone:代表用户间数据是共享的,比如一些偏平台侧的数据。

RZone:是单元化模式,适用于用户侧的流水数据,比如评价、弹幕。

CZone:介于GZone和RZone之间,可以在用户之间共享,也可以在可用区本地读写,接受一定的数据延迟和不一致性。

B站有多个机房,但机房定位比较乱。

后续对机房定位进行了梳理,物理机房按逻辑进行划分,映射为不同的可用区,比如上海四个物理机房,划分为两个可用区,两个可用区用来做GZone服务部署。

因为两个可用区都在上海,做同城双活网络延迟低,基本不存在服务延迟问题。

B站很多业务场景都适合做同城双活,因为很多数据都偏向于用户之间共享。

用DCND做多活的Router层的事情,将用户请求路由分发,可以基于用户的Mid或用户设备ID来做路由,分发到不同的可用区。

不同可用区服务,会通过proxy模式访问缓存、KV、DB。

GZS组件,用来进行多活全局管控。

在713之后,对多活组件做了优化。

DCND层面:支持通过用户ID或设备ID来hash路由到不同机房,同时支持用户流量在多机房的动态权重。

Service层面:最开始B站做同城双活时,没有实现写功能,那是还没有proxy,现在有了proxy,可以让业务方改造写了,通过存储的proxy来路由到主可用区。

Proxy层面:通过proxy模式支持kv和db,实现读写分离和failover。

GZS层面:GZS用来做多活业务,业务应用,api元信息管理,包括业务、多活、切量的编排。

GZS里,有一个invoker管控平台,会与内部的业务树、Dashboard、Comet多个平台联动,实现多活流程:编排-切量-审批-巡检-可观测。

多活流程如下:

  1. 多活规则元信息获取;
  2. 对平台进行多活演练;
  3. 多活编排、接入流程;
  4. 审批、巡检、可观测性增强;

多活的定义编排

多活编排,首先要确定的就是多活业务的范围是一个业务还是一个业务域,比如评论、弹幕这些都是业务,他的边界比较清晰。

而业务域则是业务的集合,比如直播、电商这些就是业务域,它下面有哪些规则、哪些DB、哪些kv存储都要编排下来,这个工作量是非常大的,所以业务域是不支持编排的。

所以最终采用的方案,是业务先做好编排,在基于业务的元信息聚合成业务域。

还要确定业务有哪些DB,具体的多活模式是什么,GZone还是RZone。

接入层的编排也需要了解它多活的规则是什么,一个服务、产品对外会有多个url和规则,需要编排定义出哪些规则是支持多活的。这个多活的规则调度是使用设备ID还是用户IP,这些都是需要明确编排定义的。

这些编排确定之后,会生成一个审批流,由研发或SRE同学确认这次编排是否正确。

多活的切量编排

编排定义确定之后,就可以发起切量了。

切量的时候首先要选择业务范围,是业务还是业务域。

然后选择切量的权重,可以精确控制流量。

还需要体现,切量是否需要切DB、KV。大多时候只是切DCDN流量即可,切DB需要考虑可能的数据冲突和修复问题。

切量编排完成后,会生成切量审批,审批通过SRE或CDN负责人,以工单形式明确一些操作,把每一个编排每一个层面内容变更的diff体现出来,让大家直观看到变更的内容。

切量可视化

切量审批完成后,就进入切量环节了,需要做一些前置的风险校验。

包括容量巡检、延迟巡检、隔离巡检。

容量巡检,需要看应用的cpu、缓存的cpu、db和kv的cpu。还会对连接池进行巡检,还会做一些限流配置的巡检,防止不同可用区限流配置不同。

延迟巡检,因为使用了GZone,所以DB和KV同步延迟较低,同城双活一般1ms延迟,没有什么问题。

隔离巡检,主要是看DB和kv切换是否有跨业务的混用情况,比如如果想切评论业务,发现弹幕业务也在用这个db,那这个切量会影响评论和弹幕,就会发出通知提示相关业务研发同学。

通过监控巡检的各种相关指标、业务活动流量、业务/应用的SLO指标,实现切量可观测。

通过实时监控,关注切量状态是否符合预期,业务指标和一些运维指标,可视化是非常重要的。

管控平台自身高可用

切量依赖于管控平台,那管控平台也需要做到高可用。

有的公司业务做了高可用,但研发的控制面反而没建设高可用,导致关键时刻控制面操作不了,影响了整体的高可用效果。

管控平台的高可用:做了同城双活部署模式、降级、执行效率。

管控平台按照GZone模式部署,依赖的一些核心服务,比如DCND、KV、DB也做了GZone模式部署。切量演练时,验证是否可以做到双活容灾。

713故障时,因为登录不了鉴权系统,导致不能及时处理问题,现在已经改为登录认证可降级了,不强依赖于登录态。

同样,也不能因为审批流挂了,导致多活切不了,所以当审批平台挂了,审批是可以降级跳过的。

定期会对这些工具平台做故障演练,模拟审批挂了看看降级措施是否符合预期。

对于一些操作成本高的基础组件,做了效率层面的优化,比如失败了可以快速重试、部分失败可以跳过,保证节点切掉,最后再统一处理失败节点。

在切量过程中,如果发现服务有性能问题、容量问题,或机房承载不了流量,导致不符合切量预期的,可以做到快速一键回滚。

做做了以上一系列优化后,是需要经常做演练以验证效果的。

在2022年上半年,B站做了60次以上的切量演练,没出现过什么问题,不断驱动了在巡检可观测上面的优化。

故障发生后,不是仅仅修复故障,更重要的是要善于从踩过的坑中总结经验,找到优化和提升的方向,只有这样系统才能不断稳健发展。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 春哥talk 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
内容分发网络 CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档