前言
BFF是一种Web架构,全名为Backends For Frontends,即为服务于前端的后端。这个词来源于Sam Newman的一篇文章:Pattern: Backends For Frontends[1]。BFF一般指的是在前端与后端之间加增加一个中间层。为什么要在前端和后端之间增加一个BFF层呢?
计算机科学家David Wheeler曾经说过一句话:All problems in computer science can be solved by another level of indirection.计算机科学中的所有问题都可以通过加一层来解决。因此,需要使用BFF的场景,肯定是普通的前后端开发模式遇到了部分问题。例如在Sam Newman的文章中就描述了BFF解决多个展示端的场景。
多端功能展示
在系统一开始开发的时候只考虑了PC网页端的设计,服务器端API是为了PC网页端而服务的。但是后来随着移动互联网的兴起,移动端开始流行,决定在原有服务端的基础上开发移动端App,复用之前的API,但是原有API是为了PC端设计的,并不符合移动端的需求。
PC端的需求与移动端并不一定完全相同,现有接口无法满足所有移动端的新需求。
PC端电脑性能强,可以并发请求多个接口或进行部分较复杂的数据处理,但是移动端性能低,如果使用同样的多个接口,由前端组装数据,页面展示可能会出现延迟和卡顿现象。
PC端的屏幕较大,展示内容较多且全面。但是移动端屏幕小,展示内容较少。而且部分数据的获取并不容易,需要后端调用许多服务。如果移动端复用PC端接口,会获取和传输部分无用数据,不仅消耗服务端资源,还浪费网络带宽。
而且随着科技的发展和用户的需求,不同的展示端越来越多,在不仅在手机上会区分Android端,IOS端,而且还会有平板电脑端,手机网页端,PC网页端,PC的APP端等等。这些端的页面设计各不相同,对于数据的需求也不相同。假设我们复用同一个服务端和API接口,如果出现不满足需求的场景就加接口加字段,那么随着这些不同客户端的开发和迭代,服务端会变的大而臃肿,效率低下。而且同一个接口提供给太多前端调用,涉及到太多的逻辑,复杂性越来越高。
因此,更好的方式是服务端对展示进行解耦,服务端只负责提供数据,有专门的展示端负责前端的展示业务。这里的展示端就是BFF层。
不同业务场景的展示模式差异
在某些业务中,客户端的类型只有一种,但是在不同的场景下,展示的模式有差异。比如在美团的BFF实践[2]中,不同行业的团购货架展示模块不同,是两套独立定义的产品逻辑,并且会各自迭代。
在这种业务场景下,虽然是同一个客户端,但是业务不同,需求的数据格式和类型也不同,因此遇到与上面多端展示类似的接口问题。
短生命周期的需求
还有一种情形,是闲鱼团队遇到的短生命周期的需求[3]。在普通的业务场景下,服务端正常稳定迭代开发。但是偶尔会有一些特殊的运营活动,这种活动时间较短,可能仅仅持续几天时间。
如果仅仅为了这些几天的活动,每次都要开新API,联调,甚至修改原有服务端的逻辑,成本较大,而且较为低效。如果加一层BFF,让前端可以直接获取数据,那么开发和联调会变的简单很多。
业务整合需要
在某些情形下,业务后端和需求比较复杂,例如这篇文章涉及到的场景[4],有一个Moments App,包含了像用户管理,关系管理,信息,头像,点赞等多种多种后端微服务。这些服务在前端展示的逻辑耦合性较强。比如有些需要串行处理,例如得到服务1的结果才可以调用服务2;有些则可以并行处理。而数据合并和整理的逻辑额较为复杂。
网易云音乐也使用BFF进行微服务的调度以及数据的组装和适配。
这时候可以设立一个BFF层,作为一个数据整合服务,将调用不同微服务接口,与数据处理的复杂逻辑都在BFF端中实现,降低了前端的复杂度,也提高了响应效率。
处理部分展示相关的业务
在使用了BFF之后,部分页面展示相关的业务逻辑可以抽象出来,交由BFF端处理。
例如数据导出Excel下载服务,输入导入Excel上传服务。BFF层可以接收用导入的Excel,解析并处理表格数据,然后提供给服务端。在导出时,也可以调用服务端API获取数据,由BFF端整合提供给前端下载。在这种情形下,服务端只需要提供一个展示接口,就可以满足页面展示和导出两种不同格式的展示需求。导入也是同理。而且假设表格与页面展示要求的数据格式不同,例如导入时部分字段值需要作转换,那么也可以由BFF端处理这种差异。
BFF的类型
BFF本身仅仅是一个概念,实现方式有多种,在实际中我们要根据不同的场景选取不同的方案。按照大类分,主要有单一BFF和多端BFF。
单一BFF
单一的BFF主要对接服务端,根据展示服务的需求组装数据提供给每个端或者每种业务进行展示。
很多单一BFF都会用到GraphGL,他是由Facebook开发的数据查询工具。通过该工具,可以将不稳定的数据组装部分从稳定的业务数据逻辑中剥离,使数据控制逻辑前移,开发模式由“下发数据”转变成“取数据”的过程。
例如美团,闲鱼,网易云音乐等的BFF,都提供了按需查询能力,一个BFF对接多种客户端或者多种业务的需求。下图是美团使用的BFF架构设计。
多端BFF
多端BFF是指每种业务或者每种客户端采用自己独立的BFF层,这样每种客户端的服务更加灵活,不同的BFF端对于展示服务解耦性更高。
前端BFF与后端BFF
从技术上分,BFF又可以分为前端BFF和后端BFF。即BFF层由前端团队主导或者后端团队主导。前端团队的BFF一般使用Node.js,后端团队则会使用Java或者其他服务端语言。
如果使用前端BFF,可以实现谁使用谁开发,一定程序生避免了前后端实现的上不必要的沟通成本。但需要前端团队有一服务端开发经验,对前端团队的技术建设有较高需求。但是前端也能更深入的接触业务逻辑,对于重展示的业务需求有一定优势。例如淘宝的实践:大淘宝技术行业FaaS化实战经验分享[8]。
传统接口与按需查询
传统接口模式即正常开发接口,固定入参和返回数据格式,供前端调用。按需查询模式即前端调用接口时指定需要哪些数据,前端自主进行按需查询。GraphQL即是使用按需查询的模式。
BFF的其他特点
与ServerLess集成
使用前端BFF时,前端开发可能缺乏运维经验,而且在高可用,并发性等问题上可能会遇到挑战。如果结合Serverless实现自动扩容,弹性伸缩等功能,可以解决一些BFF的问题。
BFF与网关
网关可以提供路由,认证,监控,日志等服务。网关可以与BFF集成在一起,也可以作为独立的一层来实现。如果业务复杂,还可以在不同的BFF上层配置不同的网关。
FF的优势
通过上面的的各种问题和场景,相信我们已经知道了BFF可以解决很多场景的问题,这里总结一下BFF的优势:
服务端对数据展示服务进行解耦,展示服务由独立的BFF端提供,服务端可以聚焦于业务处理。
多端展示或者多业务展示时,对与数据获取有更好的灵活性,避免数据冗余造成消耗服务端资源。
对于复杂的前端展示,将数据获取和组装的负责逻辑在BFF端执行,降低前端处理的复杂度,提高前端页面响应效率。
部分展示业务,可以抽象出来利用BFF实现,对于服务端实现接口复用。
降低多端业务的耦合性,避免不同端业务开发互相影响。
其他优势,包括数据缓存,接口安全校验等。