前世今生
在开始介绍网关之前,首先介绍两个概念BFF(Backend For Frontend)和网关,这两个概念及其容易混淆,所以首先借用Netflix和SoundCloud两个公司的系统架构层次演化来说明一下。
Netflix微服务分层架构(2017以及以前)
Netflix 2017年
这个分层架构共分四个层次
- 用户体验层,据说Netflix要支持超过一千种的不同设备体验,这个对Netflix技术团队特别是前端团队是一个巨大的挑战。
- 网关路由层,Netflix使用Zuul网关作为服务路由层,同时兼具安全认证,监控,限流熔断等跨横切面功能。Zuul网关无状态以集群方式部署,前面依赖AWS ELB做负载均衡。
- 边界API层,Netflix的裁剪聚合和适配层,也就是BFF层,将后端微服务,适配到不同的前端体验。在Netflix体系中,该层也称Edge Service Layer。
- 微服务层,Netflix的核心领域服务,也称中间层(Middle Tier)服务。
网关+边界API层(BFF)+一些前端服务(如安全认证,Playback相关服务,DRM等),统一由一个Netflix的前端团队负责,该团队也称边界工程(Edge Engineering)团队。
- 因为Netflix要应对处理的设备类型巨多,所以它们在边界层投入了大量工程技术资源,2017年前Netflix的边界API层(BFF)具有下面架构特点:
- 整个边界API层(BFF)住在一个PaaS平台里头,称为Edge PaaS。
- Edge PaaS本质上是一个动态脚本平台(Dyanmic Scripting Platform),支持使用Groovy等JVM脚本语言,方便前端团队快速聚合裁剪后端微服务,并向前端设备暴露友好的API。之所以使用动态脚本语言Groovy,主要是考虑脚本语言对前端开发的友好性和生产率。
- Edge PaaS里头同时预置后端微服务的Java客户端SDK,方便Groovy脚本调用后端服务,同时对客户端进行Hystrix埋点,保障对后台微服务调用的稳定性。
- 由于前端需求变更比较频繁,所以Edge PaaS里头的脚本一般更新也比较频繁,前端团队可以按需每日更新,上传动态脚本即可。
- 如果后端微服务有升级更新,一般需要升级Edge PaaS里头的客户端SDK,但是这个不是频繁操作,一般以固定周期(比如两周一个full release)发生,但是集成回归测试成本还是比较高的。
Netflix微服务分层架构(2018)
上述的Edge PaaS其实是一个单块架构,随着Netflix的前端业务变得更加复杂,Edge PaaS也逐渐遭遇康威法则的约束,暴露出如下问题:
- Edge PaaS里头同时耦合了前端聚合裁剪适配和后端API/SDK逻辑,当后端API有升级,一般需要升级Edge PaaS里头的客户端SDK,这种升级可能因不兼容和测试不充分,造成前端业务代码出问题。总体上前后端团队因升级、集成测试而造成的沟通协调成本非常大。
- 所有面向用户体验的脚本逻辑都住在一套Edge PaaS里头,缺乏隔离性,当某个团队的脚本有bug,很容易负面影响到其它脚本。整个Edge PaaS也是一个大单点(Single Point of Failure),严重脚本缺陷或者流量洪峰可致集群宕机。
- 前端脚本有上传快和动态加载等优势,但是本地调试不方便,很多依赖的环境(Edge PaaS + API/SDK)难以在本地开发环境复制,造成开发反馈效率低下,出现问题排障困难。
- 为解决上述问题,Netflix边界工程团队对Edge PaaS的架构进行了调整,从单块一分为二,新的架构如下图所示:
主要变化是将边界API层分成两个子层次:
API聚合层,专注对后端微服务进行聚合,提供前端友好、抽象统一的API。API聚合层主要基于Java+后台服务的客户端SDK实现。API聚合层还按业务功能进行分集群部署(API Sharding)。
设备适配层BFF,专注对API聚合层的服务进行裁剪和适配,提供给不同的用户体验展示。
- 设备聚合层采用对前端开发友好的Node.js框架,各个团队的服务可以独立部署在容器环境(Netflix的容器云Titus)中,使用容器机制进行隔离,避免相互干扰。Node.js+容器在Netflix称为NodeQuark平台。NodeQuark环境在开发人员本地可以搭建,方便开发本地调试。
- 经过拆分,当前Netflix演化出一个五层的微服务分层架构,前面三层(用户体验、网关路由和设备适配层)专注解决前端开发人员生产率的问题;后端两层(API聚合层和微服务层)专注解决领域抽象和运维监控稳定性问题。整个体系架构层次职责分明,初步解决了之前单块Edge PaaS的诸多问题,解放了生产率。
结论
- Netflix采用经典的微服务分层架构,前端体验->网关路由->边界API层(BFF)->后端微服务。这个分层架构可供一线企业实践微服务参考。
- 近年,为了进一步提升前端研发效率,Netflix又将边界API层(BFF)拆分成两个子层次,设备适配层BFF和API聚合层。总体演化出一个五层的微服务分层架构。增加新的层次对于Netflix这种体量的公司来说,有其架构合理性,但一般企业没必要细分5层,采用上述经典4层架构就OK了。BFF层也未必要采用脚本nodejs之类,java/.net等强类型语言开发也OK,毕竟一般企业没有Netflix那么多的用户设备要处理。
- 从Netflix架构体系演变我们可以看出,为了提升研发效率,它的架构经过很多层细分,额外分层会带来一定的性能损失。但是对于前沿大体量的互联网公司,性能一般并不是其架构的首要考量,灵活性、可治理性和研发效率才是它们的首要考量。性能的损失一般可以通过云计算+水平扩展+缓存等手段来弥补。
SoundCloud
下面继续以SoundCloud公司为案例,通过一系列架构视图,展示SoundCloud微服务架构的分层组织方式。如果你阅读并理解了前面两篇文章的内容,那么就比较容易理解本文的内容,所有本文的分析会相对简单一点。
注,SoundCloud是一家德国网站,提供音乐分享社区服务,成长很快,Alexa世界排名已进入200位以内。
- SouldCloud采用经典的三层微服务架构,用户体验层->边界BFF层->后端微服务层
- SoundCloud的BFF主要分为四类:
- 面向主站的Api-V2 BFF
- 面向移动端的Api-mobile BFF
- 面向嵌入页面场景的Api-embeded BFF
- 面向开放平台场景的Public API BFF
- SoundCloud没有像Netflix那样的独立的网关Gateway层,它的BFF层融合了网关功能+服务聚合裁剪和适配功能
- SoundCloud的微服务分层架构也是为了应对业务和技术挑战,不断演化出来的。关于其内部微服务的演进历程,以及BFF在演进中扮演的角色。
image.png
总结
- Netflix的微服务架构有独立的网关层,SoundCloud则没有独立网关层,它的网关和BFF层是融合在一起的。我认为这个和两家公司的业务体量和团队规模不同有关,Netflix业务体量更大也更复杂,需要独立的网关层实现架构上的关注分离,保障研发交付效率。SoundCloud则业务体量和团队规模相对小,暂时还没有分解那么细。将网关和BFF融合的做法,在国内很多公司也是这么实践的。
- SoundCloud对其微服务还进行了一层细分,包括基础服务+增值服务,这个应该是架构师根据需要,额外定义的一种架构分层规范,有助于研发人员更清晰理解架构,并遵循架构规范开展研发。
- Netflix/SoundCloud等大公司的微服务分层架构仅供参考,各家做法有差异,但是背后原理相同。架构师要理解其背后的分布式原理,然后灵活应用,不可拘泥照搬。
- SoundCloud还给出微服务架构的一种更抽象的描述,如下图所示,微服务架构本质上可以理解成是一种分布式的企业操作系统
- 内核是一个企业的业务领域基础服务
- 第二层是BFF,将基础服务聚合裁剪适配,暴露面向不同用户体验的API
- 第三层是面向不同用户体验(无线PC\开放平台等)的客户应用
- 最外层是使用这个企业操作系统的用户
API网关概念介绍
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
通常情况下, API 网关要做很多工作,它作为一个系统的后端总入口,承载着所有服务的组合路由转换等工作,除此之外,我们一般也会把安全,限流,缓存,日志,监控,重试,熔断等放到 API 网关来做,那么可以试想在高并发的情况下,这里可能会出现一个性能瓶颈。
另外,如果没有开源项目的支撑前提下,自己来做这样一套东西,是非常大的一个工作量,而且还要做 API 网关本身的高可用等,如果一旦做不好,有可能最先挂掉的不是你的其他服务,而就是这个API网关。
作者:介鬼
链接:https://www.jianshu.com/p/a8b0ca4932e1