后端与系统架构3140 字

B站亿级API网关重构之路

·全库 548 / 611

《B站亿级API网关重构之路》共 0.3 万字,通篇围绕 微服务、安全、架构、监控 展开,归在「后端与系统架构」这一层。

覆盖微服务安全架构监控成本交付

适合给 AI 系统搭底座、要管得住的人

目录骨架(4 节)
  1. 垂直 BFF 时代 2016-2019
  2. 在电商和直播业务下重构API网关
  3. 从多个网关到最后一个统一网关 2022 - 至今
  4. 未来展望

本次分享内容

  1. 项目背景
  2. 垂直BFF时代
  3. 在电商和直播业务下重构API网关
  4. 未来展望

背景

如果你在 2015 年就使用 B 站,那么你一定不会忘记那一年 B 站工作日选择性崩溃,周末必然性崩溃的一段时间。也是那一年 B 站投稿量激增,访问量随之成倍上升,而过去的 PHP 全家桶也开始逐渐展露出颓势,运维难、监控难、排查故障难、调用路径深不见底,而也就是在这一年,B 站开始正式用 Go 重构 B 站。

B 站第一个 Go 项目:bilizone

bilizone 其实还是一个大而全的应用,bilizone 在当时重构的主要意义是将谁也理不清的 PHP 逻辑梳理成了一个比较标准的 Go 应用。

bilizone 在当时最大的意义就是为用户终端提供了基本稳定的数据结构、相对可靠的接口和比较有效的监控。但因 bilizone 依旧是一个单体应用,所以它依旧继承了单体应用所具有的缺点:

  • 代码复杂度高

方法被滥用、超时设置混乱、牵一发而动全身

  • 一挂全挂

最常见的:超时设置不合理,Goroutine 大量堆积,雪崩

Goroutine是Go语⾔中并发的执⾏单位。 Goroutine底层是使⽤协程(coroutine)实现, coroutine 是⼀种运⾏在⽤户态的⽤户线程(参考操作系统原理:内核态,⽤户态)它可以由语⾔和框架层调度。 Go在语⾔层⾯实现了调度器,同时对⽹络, IO库进⾏了封装处理,屏蔽了操作系统层⾯的复杂的细节,在语⾔层⾯提供统⼀的关键字⽀持。

  • 测试及维护成本高

小改动都需要测试所有 case,运维发布胆战心惊

所以此时 B 站的崩溃频率虽然已经有所降低,但一炸全炸的问题依旧是一个心腹大患。

而再接下来的一次重构,B 站微服务的全局面貌就将初具雏形。

为了实现微服务模式下的 bilibili,我们将一个 bilizone 应用拆分成多个独立业务应用,如账号、稿件、广告等等,这些业务通过 SLB 直接对外提供 API。

当时的调用模式如下图所示:

但是随着功能拆分后,我们对外暴露了一批微服务,但是因为缺乏统一的出口而面临了不少困难:

  • 客户端与微服务直接通信,强耦合
  • 需要多次请求,客户端聚合数据,工作量巨大,延迟高。
  • 协议不利于统一,各个部门间有差异,反而需要通过客户端来兼容。
  • 面向 “端” 的 API 适配,耦合到了内部服务。
  • 多终端兼容逻辑复杂,每个服务都需要处理。
  • 统一逻辑无法收敛,比如安全认证、限流。

基于上述问题和我们想要将对端的处理进行内聚的想法,我们自然的而然的就想到在客户端与后端服务之间加一个 app-interface 的组件,这就是接下来的 BFF(Backend for Frontend)模式。

app-interface 的工作模式如下图所示:

有了这个 BFF 之后,我们可以在该服务内进行大量的数据聚合,按照业务场景来设计粗粒度的 API,给后续服务的演进带来的很多优势:

  • 轻量交互:协议精简、聚合。
  • 差异服务:数据裁剪以及聚合、针对终端定制化 API。
  • 动态升级:原有系统兼容升级,更新服务而非协议。
  • 沟通效率提升,协作模式演进为移动业务和网关小组。

BFF 可以认为是一种适配服务,将后端的微服务为客户端的需要进行适配(主要包括聚合裁剪和格式适配等逻辑),向终端设备暴露友好和统一的 API,方便无线设备接入访问后端服务,在其中可能还伴随有埋点、日志、统计等需求。

这个时期的 BFF 还有一个致命的一个问题是整个 app-interface 属于 single point of failure,严重代码缺陷或者流量洪峰可能引发集群宕机所有接口不可用。于是我们在上述基础上进一步迭代,将 app-interface 进行业务拆分,进而多套 BFF 的模式横空出世:

由此模式开始,基本确定了 B 站微服务接口的对接模式,这套模式也随之在全公司内推广开来。

垂直 BFF 时代 2016-2019

当 B 站网关的架构发展为多套垂直 BFF 之后,开发团队围绕该模式平稳迭代了相当长的一段时间。而后随着 B 站业务的发展,团队人员的扩充和几次组织架构调整,此时开始出现直播、电商等独立业务,这些业务的发展我们之后再细说。而在这些调整之后,有一个团队的职责越来越清晰:主站网关组。

主站网关组的主要职责就是维护上述各类功能的 BFF 网关,此时 bilibili 的主要流量入口为粉板 App,这里可以简单细说一下粉板 App 上的所有业务组成:

主站业务

  • 网关组维护的 BFF,如推荐、稿件播放页等
  • 业务层自行维护的 BFF,如评论、弹幕、账号等

独立业务

  • 电商服务
  • 直播服务
  • 动态服务

主站业务的 BFF 其实被分为两类,一类是由网关组负责的 BFF,另一类是业务自行维护的 BFF。

而这两类 BFF 的技术栈其实基本一致,基本功能职责也相差不多,如此划分的原因是让网关组可以更专注于迭代客户端特性功能,免去理解部分独立业务场景的接口,如登陆页应该让对安全更专业账号的同学自行维护。在这里我们也可以简述一下一个新需求应该如何决定参与的 BFF :

资料里没有你的场景?

把你手上的数据和想解决的那个环节发上来,我们按具体情况回,不复述方法论。

发布需求