首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Backend For Frontend (BFF)

Backend For Frontend (BFF)

作者头像
ayqy贾杰
发布2019-06-12 14:56:05
2.3K0
发布2019-06-12 14:56:05
举报
文章被收录于专栏:黯羽轻扬黯羽轻扬

零.背景

服务端需要支持多种前端设备下的用户体验时,常常面临现有API与某一端UI紧耦合的情况

比如为PC端页面设计的API需要支持移动端,发现现有接口从设计到实现都与桌面UI展示需求强相关,无法简单适应移动端的展示需求

一.现状

一个后端API层对多个前端(PC端、移动端等)的话,一般是支持一端后,再添加更多功能来支持其它端

It’s tempting to design a single back-end API to support all clients with a reusable API.

多个前端UI要求的API相似的话,这样做没什么问题(稍微增强下现有API就能支持另一种前端体验),但移动端UI体验通常与PC端不一样

Valuable services support many variations in clients, such as mobile versus web and different forms of web interface.

例如:

  • 屏幕空间小,所能显示的数据也少
  • 建立多个连接会增加耗电,前端做数据聚合成本高
  • 交互方式差异很大,后端API需要支持的功能也不同。比如PC端填表单,移动端扫码……

所以,移动端通常要:

  • 进行不同的(或更少的)API调用,比如做聚合
  • 展示不同的(或更少量的)数据

另外,一个后端API通常要为多个前端应用提供支持,此时单一后端可能会成为版本迭代的瓶颈,因为每版工作量巨大(对接N个前端应用)。从而产生一个庞大的独立后端团队,负责给多个前端团队提供API,然后各前端团队都需要与该团队沟通变更,而该团队要平衡多个前端团队的需求优先级……继而面临跨团队协作低效、资源协调困难等问题

二.BFF的由来

由于以上种种,我们不再寄希望于一个大后端为多端体验统一提供API支持,而是给每种用户体验对应一个后端(one backend per user experience),称为Backend For Frontend (BFF),译作用户体验适配层

Consequently it’s often best to define different back-end services for each kind of front-end client.

概念上,把每个前端应用拆成两部分:客户端应用与服务端的部分(BFF)。其中,BFF是面向特定用户体验的,由实现这部分UI的前端团队负责实现及维护(即UI与对应的BFF由同一个团队负责)

These back ends should be developed by teams aligned with each front end to ensure that each back end properly meets the needs of its client.

同一个团队的优势在于:

  • 更容易根据UI来定义或调整API
  • 简化了客户端、服务端的发布流程(依赖项更少了)
  • 一个BFF只专注于一个UI,更小也更灵活

从服务的角度看,BFF实际上是限制了单一服务所支持的消费者(指前端应用)数量,从而让它们更易于使用(更贴合前端需要)和更改,并帮助开发前端应用的团队保留更多的自主权:

The simple act of limiting the number of consumers they support makes them much easier to work with and change, and helps teams developing customer-facing applications retain more autonomy.

三.具体实现

要求BFF与用户体验一对一,也就是要把一个大后端拆成多个小后端

细分粒度

既然要拆分,那应该按什么来分?细分到什么程度?

不难想到3种拆分方式:

  • 用户体验级(UI级):每一种UI交互对应一个BFF,比如PC端1个,移动端3个(例如小屏手机、中屏手机和大屏手机三者UI交互差异很大的话,有必要拆成3个BFF)
  • 端级:每种前端设备对应一个BFF,比如PC、Android、iOS、手表、车机等等
  • 团队级:每个前端团队对应一个BFF,按现有组织结构来分

建议进行用户体验级拆分,因为端级拆分如果多端UI类似的话,接口大概率是能够直接复用的,没必要拆,而组织结构是能够灵活调整的,不应该限制技术方案

对接下游服务(微服务)

每个BFF需对接多个下游服务,那么势必存在几个问题:

  • 如何对接多个技术栈不同的下游服务?
  • 如何管理、如何组合这些调用?
  • 某一个调用失败时,如何保障可用性?

统一的RPC协议能够抹平下游服务技术栈的差异;对于异步调用的管理,可以借助RxJava、Finagle等事件机制来简化这些异步流程控制;部分调用失败时的可用性问题,则可以通过在BFF层容错,同时前端保证可接受不完整的响应内容来解决

复用问题

拆开之后,多个BFF之间容易产生冗余代码,尤其是一些通用的后端逻辑(如授权、认证、限流等等)

为了消除BFF间的代码冗余,一般采用两种做法:

  • 要么多BFF合一
  • 要么在BFF之上加一层Edge API service

多B合一的话,又回到了最初的问题,因为想要灵活性才拆开,又因为想要复用而合起来……白折腾了。另一个选项是加一层网关服务(Edge API service),把通用逻辑放进去,让BFF得以专注业务逻辑:

It validates and authenticates incoming requests; it enforces rate limits to protect the platform from undue load, and it routes requests to the appropriate upstream services. Factoring these high-level features into the edge service is a huge win for platform simplicity.

回到复用问题本身,我们想消除冗余,又不想因为抽离可复用代码而导致BFF间紧耦合,所以就有了一种折衷的态度:容忍BFF间冗余、消除单BFF内冗余。也就是允许一定程度的BFF间冗余

当然,复用的前提是多BFF技术栈相同,然后识别出冗余部分,并重构掉。具体地,到需要抽离公用部分的阶段,有几个选择:

  • 提出公共库
  • 抽出去作为独立service
  • 下沉到下游服务

公共库通常是耦合的主要来源,比如调用下游服务的公共逻辑会引发BFF间耦合。独立service的方案相对更好一些,可以进一步把新service概念化到领域模型里。类似地,也可以把公用逻辑下沉到下游服务,让平级的下游服务变成有依赖的树结构

无论怎样解决复用问题,都应该在有必要进行复用时才去做,一般原则是:

Creating an abstraction when you’re about to implement something for the 3rd time.

四.应用场景

与移动设备相比,PC设备性能足够好,那么是不是能直接调多个下游服务(成本不很高),不走BFF呢?

实际上,与直接面向前端应用的下游服务相比,BFF的意义在于适合用来实现:

  • 服务端模板
  • 对数据进行聚合(合并多个接口调用)、编排(格式化成前端想要的样子)、裁剪(去掉前端不需要的信息)
  • 缓存聚合调用的结果
  • 给某种UI体验(如移动端)提供特定功能
  • 供第三方使用的API,便于维护因第三方限制而添加的那部分逻辑

因为BFF是位于下游服务之上的一层,并且细分到用户体验粒度,所以要比下游服务更灵活,尤其适合为第三方提供定制API等差异化场景

五.业界实践

按照BFF理念,把大后端按前端体验拆分开,如下图:

具体实践中,BFF通常不是图示的样子,主要变化在于:

  • 按业务线拆分BFF
  • 加一层网关,负责实现路由、认证、监控、限流熔断、安全等功能

按业务线拆分的BFF更像是建立在下游基础服务之上的业务型微服务,只是这些微服务由对应业务的前端团队负责开发维护。广义的,可以理解为更细粒度的BFF,即每块业务对应一个BFF(不再按用户体验差异去分)

网关层负责实现通用的边界服务,如认证、限流等,让BFF更专注于业务相关的部分:

前端体验
--------------------
 ^      ^
 |      |
   网关
------------
BFF    BFF
-----  -----
^ ^    ^ ^
/   \  /   \
--------------------
下游服务

更有甚者,把网关层也拆开与BFF一一对应:

前端体验
--------------------
 ^      ^
 |      |
网关    网关
-----  -----
BFF    BFF
-----  -----
^ ^    ^ ^
/   \  /   \
--------------------
下游服务

P.S.另外,还有不引入BFF,而只添一层转发服务来解决数据的聚合、编排、裁剪等问题的,类似于GraphQL,但容易出现无意义的数据透传,所以一般不是全覆盖的(并非所有数据请求都走转发服务):

前端体验
--------------------
  ^           ^
  |           |
转发服务        |
--------       |
 ^  ^         |
/    \        |
--------------------
下游服务

探索

实践中对BFF的探索方向主要有3个:

  • 稳定性:保障BFF的可靠性,如通过日志、错误分析、监控、报警等手段
  • 同构:让BFF与前端体验使用相同的技术栈,如基于Node的同构方案
  • 一体化:一方面针对下游服务提供mock方案,另一方面允许同构、非同构应用共存

毕竟在BFF模式下,要求前端开发掌握一定程度的全栈知识(如服务端技能,运维、安全等知识),所以,自然地想要通过同构或一体化方案来提升开发体验,降低门槛,让技术无感化

希望越来越多的开发者,可以不用再关注流程、构建、环境、部署等各种事,希望能做到技术无感化(Techless),让每一位开发着能安安静静的快乐编码。

六.优势

关注点分离

BFF模式最大好处是关注点分离(separation of concerns),下游服务可以专注于业务领域模型,前端UI专注于用户体验:

后端可以专注于业务领域,更多从领域模型的视角去思考问题,页面视角的数据则交给前端型全栈工程师去搞定。领域模型与页面数据是两种思维模式,通过BFF可以很好地解耦开,让彼此更专业高效。

从分工的角度看:

BFF模式不仅仅是一种技术架构,从社会分工角度讲,BFF更是一种多元价值导向的分层架构,每一层都有不错的空间去施展。

自主权

从团队角度看,传统的前后端分离主要问题在于:

  • 服务的扩展性及复杂度
  • 前后端团队的多对一关系,因为前端团队必然需要细分(由于技术实现的差异,需要专人来做)
  • 跨团队协作成本,例如前端UI开发过程中,后端API可能发生变化(存在跨团队的沟通协调成本)

在BFF模式下,API的owner是负责实现对应用户体验的前端团队,也就是说前端团队拥有API的自主权,可以快速调整变化

前端与BFF团队一体化的另一个好处是,可以灵活选择由客户端实现还是服务实现(比如通用性强的由服务实现,甚至为了快速发版过审也可以由服务实现),而不需要跨团队协调

参考资料

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端向后 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零.背景
  • 一.现状
  • 二.BFF的由来
  • 三.具体实现
    • 细分粒度
      • 对接下游服务(微服务)
        • 复用问题
        • 四.应用场景
        • 五.业界实践
          • 探索
          • 六.优势
            • 关注点分离
              • 自主权
                • 参考资料
                相关产品与服务
                Prowork 团队协同
                ProWork 团队协同(以下简称 ProWork )是便捷高效的协同平台,为团队中的不同角色提供支持。团队成员可以通过日历、清单来规划每⽇的工作,同时管理者也可以通过统计报表随时掌握团队状况。ProWork 摒弃了僵化的流程,通过灵活轻量的任务管理体系,满足不同团队的实际情况,目前 ProWork 所有功能均可免费使用。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档