本文由B站微服务技术团队资深开发工程师周佳辉原创分享。

1、引言

如果你在 2015 年就使用 B 站,那么你一定不会忘记那一年 B 站工作日选择性崩溃,周末必然性崩溃的一段时间。

也是那一年 B 站投稿量激增,访问量随之成倍上升,而过去的 PHP 全家桶也开始逐渐展露出颓势,运维难、监控难、排查故障难、调用路径深不见底。

也就是在这一年,B 站开始正式用 Go 重构 B 站,从此B站的API网关技术子开始了从0到1的持续演进。。。

* 补充说明:本次 API 网关演进也以开源形式进行了开发,源码详见本文“12、本文源码”。

PS:本文分享的API网关涉及到的主要是HTTP短连接,虽然跟长连接技术有些差异,但从架构设计思路和实践上是一脉相承的,所以也就收录到了本《长连接网关技术专题》系列文章中。

学习交流:

(本文已同步发布于:http://www.52im.net/thread-3941-1-1.html

2、关于作者

周佳辉:哔哩哔哩资深开发工程师。始终以简单为核心的技术设计理念,追求极致简单有效的后端架构。

2017 年加入 B 站,先后从事账号、网关、基础库等开发工作。编码 C/V 技能传授者,技术文档背诵者。开源社区爱好者,安全技术爱好者,云计算行业活跃用户,网络工程熟练工。史诗级 bug 生产者,熟练掌握 bug 产生的各类场景。

3、专题目录

本文是专题系列文章的第8篇,总目录如下:

4、正式用Go重构B站

鉴于引言中所列举的各种技术问题,也是在2015年,财队开始正式用 Go 重构 B 站。

B站第一个 Go 项目——bilizone,由冠冠老师(郝冠伟)花了一个周末时间编码完成。

commit 4ccb1497ca6d94cec0ea1b2555dd1859e6f4f223

Author: felixhao <g******[url=mailto:1@gmail.com]1@gmail.com[/url]>

Date:   Wed Jul 1 18:55:00 2015 +0800

project init

commit 6e338bc0ee638621e01918adb183747cf2a9e567

Author: 郝冠伟 <h*******@bilibili.com>

Date:   Wed Jul 1 11:21:18 2015 +0800

readme

▲ 郝冠伟:哔哩哔哩主站技术中心架构师

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

bilizone 在当时最大的意义就是为用户终端提供了基本稳定的数据结构、相对可靠的接口和比较有效的监控。

但因 bilizone 依旧是一个单体应用,所以它依旧继承了单体应用所具有的缺点:

  • 1)代码复杂度高:方法被滥用、超时设置混乱、牵一发而动全身;
  • 2)一挂全挂:最常见的比如,超时设置不合理、goroutine 大量堆积、雪崩;
  • 3)测试及维护成本高:小改动都需要测试所有 case,运维发布胆战心惊。

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

5、基于微服务的B站架构初具雏形

鉴于bilizone所面临的单体应用技术缺点,接下来的一次重构,让B站基于微服务的全局架构面貌就将初具雏形。

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

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

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

这些困难主要是:

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

6、基于BFF模式的微服务架构

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

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

有了这个 BFF 之后,我们可以在该服务内进行大量的数据聚合,按照业务场景来设计粗粒度的 API。

这样,后续服务的演进也带来了很多优势:

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

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

然而,这个时期的 BFF 还有一个致命的一个问题是——整个 app-interface 属于 single point of failure,严重代码缺陷或者流量洪峰可能引发集群宕机所有接口不可用。

7、基于多套BFF模式的微服务架构

针对上节中BFF模式下架构的技术问题,于是我们在上述基础上进一步迭代,将 app-interface 进行业务拆分。

进而多套 BFF 的模式横空出世:

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

8、垂直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 进行直接交互。

9、基于业务的统一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)。

10、从基于业务的多网关到全局统一网关(2022年至今)

在这两三年的时间里,各个业务团队或多或少都有自己业务网关组建独立的维护团队,也为网关的功能作出过相当多的投入。

但随着 B 站业务的发展,公司级中间件功能的不断更替演进,如果将对接各个中间件的工作在每个网关上都实现一次的话带来的人力投入和沟通成本会相当巨大,且实现标准不统一、运营方式不统一无法起到 API 网关所带来的最佳收益。

因此微服务团队开发了一款 B 站内部意义上的标准 API 网关(全局统一API网关),该 API 网关汇集以往各型网关中流量治理的优秀经验,对相关功能做出完善设计改进。

该 API 网关的目前的主要功能除了常规的限流、熔断、降级、染色外,还会基于这些基础功能和公司各类中间件的基础上,提供各种额外能力。

这些额外进阶型AP 质量治理的相关功能主要是:

  • 1)全链路灰度;
  • 2)流量采样分析、回放;
  • 3)流量安全控制;
  • ...

业务团队在接入 API 网关后都可以一并获得这些功能,为业务的迅速迭代做出力所能及的保障。

11、不仅仅是 API 网关

在开发 API 网关的同时,我们也会更进一步关注业务团队开发、对接 API 时的体验,我们将以网关作为统一标准 API 规范的起点,为业务团队提供更有效的 API 开发生态。

这些API 开发生态可能是:

  • 1)规划 API 业务域,简化 SRE 运维;
  • 2)标准 API 元信息平台;
  • 3)精确的 API 文档和调试工具;
  • 4)类型安全的 API 集成 SDK;
  • 5)API 兼容性保障服务。

API 网关是我们 API 治理生态中的一个标志性里程碑,我们希望在 API 网关的开发中能够多多倾听大家的意见,希望能有更多的声音来帮助我们理清思路。

本次 API 网关演进也以开源形式进行了开发,在这里欢迎大家指导(本次源码详见本文“12、本文源码”)。

12、本文源码

主地址:https://github.com/go-kratos/gateway

备地址:https://github.com/52im/gateway

或从原文链接中下载附件:http://www.52im.net/thread-3941-1-1.html

13、参考资料

[1] 喜马拉雅自研亿级API网关技术实践

[2] 手淘亿级移动端接入层网关的技术演进之路

[3] 从100到1000万高并发的架构演进之路

[4] 一文读懂大型分布式系统设计的方方面面

[5] 零基础理解大型分布式架构的演进历史、技术原理、最佳实践

(本文已同步发布于:http://www.52im.net/thread-3941-1-1.html

长连接网关技术专题(八):B站基于微服务的API网关从0到1的演进之路的更多相关文章

  1. 一站式入口服务|爱奇艺微服务平台 API 网关实战 原创 弹性计算团队 爱奇艺技术产品团队

    一站式入口服务|爱奇艺微服务平台 API 网关实战 原创 弹性计算团队 爱奇艺技术产品团队

  2. 微服务&#183;API网关

    阅文时长 | 3.52分钟 字数统计 | 1232字符 主要内容 | 1.什么是API网关 2.微服务中的API网关 3.几种部署策略 『微服务·API网关』 编写人 | SCscHero 编写时间 ...

  3. .net core 微服务之Api网关(Api Gateway)

    原文:.net core 微服务之Api网关(Api Gateway) 微服务网关目录 1. 微服务引子 2.使用Nginx作为api网关 3.自创api网关(重复轮子) 3.1.构建初始化 3.2. ...

  4. SOA与ESB,微服务与API网关

    SOA与ESB,微服务与API网关 SOA: ESB: 微服务: API网关: 参考资料: 1.漫画微服务,http://www.sohu.com/a/221400925_100039689 2.SO ...

  5. Net分布式系统之六:微服务之API网关

    本人建立了个人技术.工作经验的分享微信号,计划后续公众号同步更新分享,比在此更多具体.欢迎有兴趣的同学一起加入相互学习.基于上篇微服务架构分享,今天分享其中一个重要的基础组件“API网关”. 一.引言 ...

  6. 基于.NET CORE微服务框架 -Api网关服务管理

    1.前言 经过10多天的努力,surging 网关已经有了大致的雏形,后面还会持续更新完善,请大家持续关注研发的动态 最近也更新了surging新的版本 更新内容: 1. 扩展Zookeeper封装2 ...

  7. 基于spring-cloud的微服务(4)API网关zuul

    API网关是微服务架构中的很重要的一个部分,内部有多个不同的服务提供给外部来使用,API网关可以对外做统一的入口,也可以在网关上做协议转换,权限控制和请求统计和限流等其他的工作 spring-clou ...

  8. 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程 ...

  9. AspNetCore微服务下的网关-Kong(一)

    Kong是Mashape开源的高性能高可用API网关和API服务管理层.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kong在Mashape 管理了超过15,000 个A ...

  10. 微服务时代之网关相关技术选型及部署(nacos+gateway)

    1.场景描述 因要用到微服务,关于注册中心这块,与同事在技术原型上做了讨论,初步定的方案是使用:阿里巴巴的nacos+springcloud gateway,下面表格是同事整理的注册中心对比,以前用的 ...

随机推荐

  1. synchronized的四种锁状态

    Java 多线程的锁都是基于对象的,Java 中的每一个对象都可以作为一个锁. 类锁,其实就是 Class 对象的锁. Class 对象是一种特殊的 Java 对象,代表了程序中的类和接口.Java ...

  2. Mips单周期CPU设计(logisim实现)

    Logisim单周期cpu设计文档与思考题 设计文档 支持指令集 指令 格式 描述(RTL) 机器码 OPCODE/FUNCT add add rd rs rt GPR[rd] <- GPR[r ...

  3. 怎样在Linux 环境 (红帽 rhel 7.3) 安装 Python 3

    自己装的虚拟机(红帽 7),默认安装的python2.7,更新为python 3.8  自己做个记录,方便日后查看 注意:红帽的yum 需要注册才能使用,必须要替换yum,替换方法请参见:怎样替换 r ...

  4. 无套路领取《AI应用开发专栏》

    最近有些时间没有更新技术文章了,都在忙着写<AI应用开发入门>专栏,专栏已整理放到了github上,有兴趣的小伙伴可以移步github阅读,地址见文末. 1.为什么写这个文档 之前陆续写了 ...

  5. 海外SRC信息收集工具

    海外SRC信息收集 ​ 子域名爆破工具:bbot,subfinder ​ 相关测评:https://blog.blacklanternsecurity.com/p/subdomain-enumerat ...

  6. duxapp放弃了redux,在duxapp中局部、全局状态的实现方案

    全局状态 全局状态是一个很实用的功能,例如管理用户信息,组件间状态共享等功能都需要用到全局状态,react有很多成熟的全局状态管理工具,但是很多写起来太过麻烦,duxapp提供了几种应对不同场景的全局 ...

  7. Linux 练习

    目录 练习一 练习2 练习一 分析日志t.log(访问量),将各个ip地址截取,并统计出现次数,并按从大到小排序(腾讯) 每行格式:http: //192.168.200.30/index1.html ...

  8. 模拟器(Nintendo,Genesis,SFC,MD,土星,PS,PS2,PS3,Wii,Xbox等)游戏下载网址

    最近想拿个英文游戏复习复习,国内的emu618关闭之后难得寻到很完整的游戏库 通过 https://www.fantasyanime.com/mana/som2downloads.htm 找到 htt ...

  9. 『玩转Streamlit』--交互类组件

    交互类组件在Web应用程序中至关重要,它们允许用户与应用进行实时互动,能够显著提升用户体验. 用户不再只是被动地接收信息,而是可以主动地输入数据.做出选择或触发事件,从而更加深入地参与到应用中来. 此 ...

  10. Abp vNext 入门到放弃系列

    文章目录 1.模块介绍 2.模块加载机制 3.依赖注入 4.AutoMapper-- 待定 5.本地化--待定 6.模型验证--待定 7.异常处理--待定 8.缓存 9.动态代理和拦截 10.分布式锁 ...