目录
2亿用户,B站API网关如何架构
1、正式用Go重构B站
2、基于微服务的B站架构初具雏形
3、基于BFF模式的微服务架构
4、基于BFF集群的微服务架构
5、垂直BFF模式时代(2016年至2019年)
6、基于业务的统一API网关架构
7、从基于业务的多网关到全局统一网关(2022年至今)
编辑
8、不仅仅是 API 网关
作者:周佳辉:哔哩哔哩资深开发工程师。
如果你在 2015 年就已经成为 B 站的用户,那么你肯定还记得那一年 B 站工作日选择性崩溃,周末必然性崩溃的情况。
同样在那一年,B 站的投稿数量大幅增长,访问量也急剧上升,而过去的 PHP 全家桶技术开始逐渐显示出疲态,运维困难、监控困难、故障排查困难、调用路径深不可测。
因此,在 2015 年,B 站开始正式采用 Go 语言重构,从此 B 站的 API 网关技术开始了从零到一的持续演进。
面对引言中列出的各种技术问题,2015 年,B 站开始正式采用 Go 语言进行重构。B 站的第一个 Go 项目是由冠冠老师(郝冠伟)在一个周末完成的,名为 bilizone。
实际上,bilizone 是一个功能全面的应用,其重构的主要目标是将混乱的 PHP 逻辑梳理成一个标准的 Go 应用。
bilizone 在当时的最大意义在于,它为用户终端提供了基本稳定的数据结构、相对可靠的接口和有效的监控。
然而,由于 bilizone 仍然是一个单体应用,因此它仍然具有单体应用的缺点:
1)代码复杂度高:方法被滥用、超时设置混乱、牵一发而动全身;
2)一挂全挂:最常见的,比如超时设置不合理、goroutine 大量堆积、雪崩;
3)测试及维护成本高:即使是小改动,也需要测试所有 case,运维发布时总是提心吊胆。
因此,尽管此时 B 站的崩溃频率已经有所下降,但一炸全炸的问题仍然是一个心头大患。
鉴于 bilizone 面临的单体应用技术问题,接下来的一次重构使 B 站基于微服务的全局架构初具雏形。
为了实现微服务模式下的 bilibili,我们将一个 bilizone 应用拆分成多个独立的业务应用,如账号、稿件、广告等,这些业务通过 SLB 直接对外提供 API。
当时的调用模式如下图所示:
然而,在功能拆分后,我们向外部公开了一批微服务,但由于缺乏统一的出口而遇到了诸多困难。
这些困难主要是:
1)客户端与微服务直接交互,导致强耦合;
2)需要发起多次请求,客户端负责数据整合,工作量大且延迟较高;
3)协议不统一,各部门之间存在差异,反而需要客户端来实现兼容;
4)面向“端”的 API 适配,导致内部服务耦合;
5)多终端兼容逻辑复杂,每个服务都需要处理;
6)统一逻辑无法收敛,比如安全认证、限流。
鉴于前面提到的初级微服务架构所引发的技术问题,以及我们希望将对端处理进行内聚的考虑,我们自然而然地想在客户端与后端服务之间添加一个 app-interface 组件,app-interface 的工作模式如下图所示:
这个 app-interface 接口组件,对应到架构模式上,就是 BFF(Backend for Frontend)模式。
引入 BFF 后,我们可以在该服务中进行大量数据整合,并根据业务场景设计出粗粒度的 API。
这样,后续服务的演进也带来了很多优势:
1)轻量交互:协议精简、聚合;
2)差异服务:数据裁剪以及聚合、针对终端定制化 API;
3)动态升级:原有系统兼容升级,更新服务而非协议;
4)沟通效率提升:协作模式演进为移动业务和网关小组。
BFF 可以认为是一种适配服务
将后端微服务,根据客户端需求进行适配,主要包括
聚合剪裁
格式适配等
BFF 可以向终端设备展示友好且统一的 API,便于无线设备接入访问后端服务,其中可能还包含埋点、日志、统计等需求。
然而,这个阶段的 BFF 还存在一个致命问题——整个 app-interface 属于 single point of failure,严重的代码缺陷或流量洪峰可能导致集群崩溃,所有接口无法使用。
Single Point of Failure(SPoF)是指一个系统的这样一个部件,如果它失效或停止运转,将会导致整个系统不能工作。我们当然不希望看到,在一个要求高度可用性的系统中存在这样的部分,但这种情况在网络,软件应用以及其它工业系统中都存在。
针对单体 BFF 模式下Single Point of Failure(SPoF)问题,我们在此基础上进行了进一步迭代,将 app-interface 进行集群化架构,基于BFF集群的微服务架构:
由此模式开始,基本确定了 B 站微服务接口的对接模式,这套模式也随之在全公司内推广开来。
接上节,当 B 站网关的架构发展为多套垂直 BFF 之后,开发团队围绕此模式稳定迭代了相当长一段时间。
随着 B 站业务扩展、团队人员增加以及组织架构调整,直播、电商等独立业务逐渐崭露头角,这些业务的发展我们将在后续详细介绍。
在这些调整之后,一个团队的职责变得越来越明确:主站网关组。
主站网关组的主要职责是维护各类功能的 BFF 网关,此时 bilibili 的主要流量入口为粉板 App。下面我们简要介绍粉板 App 上的所有业务组成。
主站业务:
1)网关组维护的 BFF,如推荐、稿件播放页等;
2)业务层自行维护的 BFF,如评论、弹幕、账号等。
独立业务:
1)电商服务;
2)直播服务;
3)动态服务。
主站业务的 BFF 其实被分为两类:
1)一类是由网关组负责的 BFF;
2)另一类是业务自行维护的 BFF。
这两类 BFF 的技术栈基本相同,基本功能职责也相差无几。
划分的原因是让网关组能更专注于迭代客户端特性功能,无需理解部分独立业务场景的接口,如登录页应由负责安全方面的同事自行维护。
在这里我们也可以简述一下,一个新需求应该如何决定参与的 BFF :
1)如果这个功能能由业务层的业务 BFF 独立完成,则网关组无需参与;
2)如果该功能是一个客户端特性需求,如推荐流等复合型业务,需要对接公司大量部门时,则由网关同学参与开发 BFF。
当时主站技术部的后端同学遵循以上两个规则,基本能满足业务的快速开发和迭代。
我将这段时间称为垂直 BFF 时代,因为基本上主站每个业务都有各种形式的网关存在,大家通过这个网关向外提供接口,该网关与 SLB 直接交互。
接上节,我们再来谈一谈几项重要的业务:电商、直播和动态。
电商和直播其实并不是同一时期衍生的,直播在主站 PHP 时代就已诞生,而电商则稍晚一些。
当时直播的技术栈包括 C++、PHP 和 Go。在早期,大部分业务逻辑由 PHP 和 C++ 实现,稍后也逐步开始尝试在主站使用 Go 实现部分业务逻辑。其中 PHP 负责提供终端接口,C++ 主要实现核心业务功能。因此,我们可以简单地认为直播使用了由 PHP 编写的 BFF 网关。
动态团队其实派生自直播团队,因此技术栈和直播当时基本一致,这里可以简单省略。
众所周知,大部分电商团队的技术栈是 Java 和 Spring 或 Dubbo。
由于这几个业务之间几乎没有相似之处,而且大家对 gRPC 协议逐渐达成共识,因此大家在技术栈上基本上没有统一的想法,只要能互相调通即可。
然而,随着 B 站团队的进一步壮大和流量持续增长,大家逐渐发现了这套架构下的许多问题。
这些问题主要包括:
1)单个复杂模块会导致后续业务集成难度加大,根据康威法则,复杂聚合型 BFF 和多团队之间会出现不匹配问题,团队间沟通协调成本高,交付效率低下;
2)许多跨横切面逻辑,如安全认证、日志监控、限流熔断等。随着时间的推移和功能迭代,代码变得越来越复杂,技术债务逐渐累积。
在这种情况下,我们需要一个能够协调横切面的组件,将路由、认证、限流、安全等组件全部上提,实现统一更新发布,将业务集成度高的 BFF 层和通用功能服务层进行分层。
因此,大家开始引入基于业务的“统一 API 网关”架构。如下图所示:
在新的架构中:统一网关扮演了重要角色,它是解耦拆分和后续升级迁移的利器。
在统一网关的配合下:单块 BFF 实现了解耦拆分,各业务线团队可以独立开发和交付各自的微服务,研发效率大幅提升。
此外:将跨横切面逻辑从 BFF 剥离到网关上后,BFF 的开发人员可以更加专注于业务逻辑交付,实现了架构上的关注分离(Separation of Concerns)。
在过去的两三年中,各个业务团队都建立了自己的业务网关,并为网关的功能做出了很多贡献。
然而,随着 B 站业务的发展和公司级中间件功能的不断更新,如果在每个网关上都实现与各个中间件的对接,将会导致人力投入和沟通成本大幅增加,同时实现标准和运营方式的不统一也无法充分发挥 API 网关的优势。
因此,微服务团队开发了一款 B 站内部的标准 API 网关(全局统一 API 网关),该网关总结了过去各型网关在流量治理方面的优秀经验,对相关功能进行了完善的设计和改进。
目前,这款 API 网关的主要功能除了常规的限流、熔断、降级和染色之外,还基于这些基础功能和公司各类中间件,提供各种附加能力。
这些附加的高级 API 质量治理功能主要包括:
1)全链路灰度;
2)流量采样分析、回放;
3)流量安全控制;
...
业务团队在接入 API 网关后,可以同时获得这些功能,为业务的快速迭代提供有力的支持。
在开发 API 网关的过程中,我们将更加关注业务团队在开发和对接 API 时的体验。我们将以网关为起点,建立统一的 API 规范,为业务团队提供更高效的 API 开发生态。
这些 API 开发生态可能包括:
1)规划 API 业务域,简化 SRE 运维;
2)标准 API 元信息平台;
3)精确的 API 文档和调试工具;
4)类型安全的 API 集成 SDK;
5)API 兼容性保障服务。
API 网关是我们 API 治理生态的一个重要里程碑。我们希望在 API 网关的开发过程中,能够广泛听取大家的意见和建议,以便更好地理清思路。