说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、滴滴的面试资格。
最近,尼恩指导一个小伙伴简历,写了一个《高并发网关项目 》,此项目帮这个小伙拿到 字节/阿里/微博/汽车之家 面邀, 所以说,这是一个牛逼的项目。
为了帮助大家拿到更多面试机会,拿到更多大厂offer,
尼恩决定:给大家出一章视频介绍这个项目的架构和实操,《33章:10Wqps 高并发 Netty网关架构与实操》,预计月底发布。然后,提供一对一的简历指导,这里简历金光闪闪、脱胎换骨。
《33章:10Wqps 高并发 Netty网关架构与实操》 海报如下:
配合《33章:10Wqps 高并发 Netty网关架构与实操》, 尼恩会梳理几个工业级、生产级网关案例,作为架构素材、设计的素材。
前面梳理了
- 《日流量200亿,携程网关的架构设计》
- 《千万级连接,知乎如何架构长连接网关?》
- 《日200亿次调用,喜马拉雅网关的架构设计》
- 《100万级连接,爱奇艺WebSocket网关如何架构》
- 《亿级长连接,淘宝接入层网关的架构设计》
- 《单体120万连接,小爱网关如何架构?》
- 《100万级连接,石墨文档WebSocket网关如何架构?》
除了以上的7个案例,这里,尼恩又找到一个漂亮的生产级案例:
《2亿用户,B站API网关如何架构》,
注意,这又一个非常 牛逼的工业级、生产级网关案例。
这些案例,并不是尼恩的原创。这些案例,仅仅是尼恩在《33章:10Wqps 高并发 Netty网关架构与实操》备课的过程中,在互联网查找资料的时候,收集起来的,供大家学习和交流使用。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到公号【技术自由圈】获取
文章目录
2亿用户,B站API网关如何架构
作者:周佳辉:哔哩哔哩资深开发工程师。
如果你在 2015 年就已经成为 B 站的用户,那么你肯定还记得那一年 B 站工作日选择性崩溃,周末必然性崩溃的情况。
同样在那一年,B 站的投稿数量大幅增长,访问量也急剧上升,而过去的 PHP 全家桶技术开始逐渐显示出疲态,运维困难、监控困难、故障排查困难、调用路径深不可测。
因此,在 2015 年,B 站开始正式采用 Go 语言重构,从此 B 站的 API 网关技术开始了从零到一的持续演进。
1、正式用Go重构B站
面对引言中列出的各种技术问题,2015 年,B 站开始正式采用 Go 语言进行重构。B 站的第一个 Go 项目是由冠冠老师(郝冠伟)在一个周末完成的,名为 bilizone。
实际上,bilizone 是一个功能全面的应用,其重构的主要目标是将混乱的 PHP 逻辑梳理成一个标准的 Go 应用。
bilizone 在当时的最大意义在于,它为用户终端提供了基本稳定的数据结构、相对可靠的接口和有效的监控。
然而,由于 bilizone 仍然是一个单体应用,因此它仍然具有单体应用的缺点:
- 1)代码复杂度高:方法被滥用、超时设置混乱、牵一发而动全身;
- 2)一挂全挂:最常见的,比如超时设置不合理、goroutine 大量堆积、雪崩;
- 3)测试及维护成本高:即使是小改动,也需要测试所有 case,运维发布时总是提心吊胆。
因此,尽管此时 B 站的崩溃频率已经有所下降,但一炸全炸的问题仍然是一个心头大患。
2、基于微服务的B站架构初具雏形
鉴于 bilizone 面临的单体应用技术问题,接下来的一次重构使 B 站基于微服务的全局架构初具雏形。
为了实现微服务模式下的 bilibili,我们将一个 bilizone 应用拆分成多个独立的业务应用,如账号、稿件、广告等,这些业务通过 SLB 直接对外提供 API。
当时的调用模式如下图所示:
注意:请点击图像以查看清晰的视图!
然而,在功能拆分后,我们向外部公开了一批微服务,但由于缺乏统一的出口而遇到了诸多困难。
这些困难主要是:
- 1)客户端与微服务直接交互,导致强耦合;
- 2)需要发起多次请求,客户端负责数据整合,工作量大且延迟较高;
- 3)协议不统一,各部门之间存在差异,反而需要客户端来实现兼容;
- 4)面向"端"的 API 适配,导致内部服务耦合;
- 5)多终端兼容逻辑复杂,每个服务都需要处理;
- 6)统一逻辑无法收敛,比如安全认证、限流。
3、基于BFF模式的微服务架构
鉴于前面提到的初级微服务架构所引发的技术问题,以及我们希望将对端处理进行内聚的考虑,我们自然而然地想在客户端与后端服务之间添加一个 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)是指一个系统的这样一个部件,如果它失效或停止运转,将会导致整个系统不能工作。我们当然不希望看到,在一个要求高度可用性的系统中存在这样的部分,但这种情况在网络,软件应用以及其它工业系统中都存在。
4、基于BFF集群的微服务架构
针对单体 BFF 模式下Single Point of Failure(SPoF)问题,我们在此基础上进行了进一步迭代,将 app-interface 进行集群化架构,基于BFF集群的微服务架构:
注意:请点击图像以查看清晰的视图!
由此模式开始,基本确定了 B 站微服务接口的对接模式,这套模式也随之在全公司内推广开来。
5、垂直BFF模式时代(2016年至2019年)
接上节,当 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 直接交互。
6、基于业务的统一API网关架构
接上节,我们再来谈一谈几项重要的业务:电商、直播和动态。
电商和直播其实并不是同一时期衍生的,直播在主站 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)。
7、从基于业务的多网关到全局统一网关(2022年至今)
在过去的两三年中,各个业务团队都建立了自己的业务网关,并为网关的功能做出了很多贡献。
然而,随着 B 站业务的发展和公司级中间件功能的不断更新,如果在每个网关上都实现与各个中间件的对接,将会导致人力投入和沟通成本大幅增加,同时实现标准和运营方式的不统一也无法充分发挥 API 网关的优势。
因此,微服务团队开发了一款 B 站内部的标准 API 网关(全局统一 API 网关),该网关总结了过去各型网关在流量治理方面的优秀经验,对相关功能进行了完善的设计和改进。
目前,这款 API 网关的主要功能除了常规的限流、熔断、降级和染色之外,还基于这些基础功能和公司各类中间件,提供各种附加能力。
这些附加的高级 API 质量治理功能主要包括:
- 1)全链路灰度;
- 2)流量采样分析、回放;
- 3)流量安全控制;
- ...
业务团队在接入 API 网关后,可以同时获得这些功能,为业务的快速迭代提供有力的支持。
8、不仅仅是 API 网关
在开发 API 网关的过程中,我们将更加关注业务团队在开发和对接 API 时的体验。我们将以网关为起点,建立统一的 API 规范,为业务团队提供更高效的 API 开发生态。
这些 API 开发生态可能包括:
- 1)规划 API 业务域,简化 SRE 运维;
- 2)标准 API 元信息平台;
- 3)精确的 API 文档和调试工具;
- 4)类型安全的 API 集成 SDK;
- 5)API 兼容性保障服务。
API 网关是我们 API 治理生态的一个重要里程碑。我们希望在 API 网关的开发过程中,能够广泛听取大家的意见和建议,以便更好地理清思路。
说在最后:有问题可以找老架构取经
架构之路,充满了坎坷
如何顺利的跨过架构师的坎,化茧为蝶,完成架构师的顺利蜕变,是很多开发同学的梦寐以求的事情。
好事总是多磨。
架构和高级开发不一样 , 架构问题是open/开放式的,架构问题是没有标准答案的。
为了完成蜕变,很多小伙伴,耗费很多精力,耗费很多金钱。
但是,遗憾的是,蜕变之路非常曲折,甚至很多同学折腾一生都没有完成架构升级。
所以,在架构升级/转型过程中,如果确实找不到有效的方案,可以来找40岁老架构尼恩求助、帮扶。
前段时间一个小伙伴,做化工15年后,跨行来做Java,同样面临转架构难题,但是经过尼恩几轮指导,顺利拿到了Java架构师+大数据架构师。
所以,如果大家遇到转架构的难题,可以找尼恩取经,保证峰回路转。
尼恩技术圣经系列PDF
- 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
- 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
- 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
- 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
- 《大数据HBase学习圣经:一本书实现HBase学习自由》
- 《大数据Flink学习圣经:一本书实现大数据Flink自由》
- 《响应式圣经:10W字,实现Spring响应式编程自由》
- 《Go学习圣经:Go语言实现高并发CRUD业务开发》
......完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓