BFF调研-1

前端开发中存在的难问题
多端应用,不同类型客户端对数据、API有个性化的需求
服务聚合,单一后端为多个前端团队提供接口,导致跨团队协作低效,资源协调困难
问题:服务端设计的接口究竟是面向UI,还是面向通用服务?

BFF
解决方案: Backends For Frontends, 简称BFF。

BFF最适合的场景,为第三方提供定制API等差异化场景,每个用户体验(客户端)对应一个后端,

BFF作为用户体验适配层,对后端接口进行组合、处理,对数据进行:裁剪、格式化、聚合、编排。

BFF理念中,最重要的一点是:服务自治,谁使用谁开发,所以一般由前端维护。

BFF实现不限制具体技术,可以自由选型:Java/Node/PHP/Python,但大部分前端团队都会选择Node.js。

BFF的演化历程
BFF和网关(API Gateway)是微服务架构中两个重要概念,可以通过下面的例子讲解BFF的出现过程

服务化架构V1
实现单块应用的解构拆分,微服务初步完成,前端用户体验层主要是传统的服务端Web应用,服务化架构如下所示:

服务化架构V2
随着无线应用的流行,除了Web应用外,服务还需要为新的无线原生App来提供接口和数据,先采用下面的服务架构:

这样的架构的问题是:

无线App与内部为微服务强耦合
无线App需要知道内部服务的地址等细节
无线App需要对接口数据进行大量的聚合剪裁和适配逻辑
服务化架构V2.1
为了解决这个问题,在用户体验层和内部微服务层之间引入了BFF层,将后端的微服务进行适配,想用户体验层暴露有号和统一的API,方便无线设备接入访问后端服务

这种架构解决了上面的问题:

无线App与内部为微服务解耦,两边可以独立变化
无线App只需要知道BFF的地址,并且服务接口统一,不需要关心内部复杂的微服务的地址和细节
无线App需要不再需要聚合剪裁和适配逻辑,这些步骤都在BFF完成
但是随着接入设备的增加,也会有一些问题:

BFF只有一个,接入设备增加后导致要考虑匹配问题,团队之间沟通协调成本高
BFF中不仅包括了各个业务线的聚合剪裁、适配和业务逻辑,还需要引入很多跨横切面逻辑,比如安全认证、日志监控、限流熔断等,这些代码混在一起,导致代码复杂度提高
BFF如果出现错误,会导致所有应用都不可用
微服务架构V3
为了解决这个问题,引入API Gateway

在这种架构下:

BFF按团队和业务线进行解耦拆分,拆分成若干个BFF微服务,每个业务线并行开发和交付各自负责的BFF微服务
网关,一般由独立的团队负责运维,专注跨横切面的功能,包括
路由,将来自无线设备的请求路由到后端的某个微服务BFF集群
认证,对涉及敏感数据的API访问进行集中认证鉴权
监控,对API调用进行性能监控
限流熔断,网关能够进行限流熔断,保护后端服务
安全防爬,收集访问日志,通过后台分析恶意行为,阻断恶意请求
网关在客户端与BFF之间又引入了一层,让两边可以独立变化
微服务架构V4
可以对V3架构进行优化,将传统的服务端Web应用模式改为前后分离架构,前端采用H5单页技术提供给用户更好体验。

同时增加了下手是哪个第三方应用开放API的能力

拓展新的接入渠道,形成了一个完成的现代微服务架构,从外到内依次为:端用户体验层->网关层->BFF层->微服务层

具体实现
细分力度
要求把一个大后端拆分为多个小后端,有三种方式

用户体验级(UI)
端级
团队级
一般建议按照用户体验级来拆分

对接下游服务(微服务)
(1)如何对接多个技术栈不同的下游服务

RPC协议调用

(2)如何管理、组合调用

借助RXJava、Finagle等事件机制来简化这些异步流程控制

(3)某个调用失败时,如何保障可用性

在BFF层容错,同时前端保证可接受不完整相应内容

复用问题
拆分后,多个BFF间会产生冗余代码,这是不可避免的。

可以添加API网关层,将通用的后端逻辑(授权、认证、限流)放进去

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

蚂蚁财富的BFF实践
2016年时,汤尧对BFF在蚂蚁财富项目中的落地实践进行了介绍。

在引入BFF之前,蚂蚁财富的业务也遇到了上面提到的问题,主要是体验层API经常变化,导致开发效率低下。

于是引入了BFF,主要的目的是对数据进行:裁剪、格式化、聚合、编排。

一个理想的模型如下:

在实际落地过程中,形成了如下的架构:

他们在实战过程中,主要解决了一下几个问题:

(1)Node.js与Java通信

数据:跨语言序列化协议hessian
服务:Node弱类型,Java强类型,如何调用


这个调用过程一般是通过RPC协议完成的,而非通过HTTP协议。

由于我对Java没有接触,而且资料只是他当时的PPT,没有详细的讲解,没有办法理解具体是如何实现的。而且恐怕对于大多数前端开发工程师来说,与Java的通信也是BFF落地过程中一个比较严峻的挑战,而且这是在前端开发人员有比较好的Node开发能力的基础上。

(2)多App适配

在API网关层处理多个App的通用的逻辑,比如错误码管理、数据一致性、免登、业务日志等。

(3)聚合

传给客户端需要的数据,简化客户端逻辑,减少网络开销
避免无意义的透传
敏感信息过滤
(4)接口设计准则

基础服务接口:(微服务?)

细粒度
通用的功能,可能会被多个BFF用到
提供含各种状态的mock真实数据,易于同步开发(如何实现?)
BFF API设计

合理设计接口数量,太多不易维护
提供含各种状态的mock真实数据,页面不依赖server开发(如何实现?)
多协议发布(如何实现?)
规范数据格式
在落地BFF过程中,从技术角度来看:

前端和BFF由同一人完成
前端需要具备服务端技能
快速的应用发布能力(docker?)
TWA的理念与实践
在2018年的SEE Conf,蚂蚁金服的不四(知乎ID:死马)对在BFF基础上发展出来的TWA(Techless Web Application)开发体系进行了介绍(视频和PPT)。

传统的分层:

BFF负责聚合底层业务数据,给客户端提供接口,秉承谁使用谁维护的理念,一般由前端团队维护。

业务实际上分为三层:前端(HTML/CSS/JS)+ BFF(Node.js接口聚合层)+ 后端服务(Java)

BFF on Chari是蚂蚁自研的,基于Egg.js的BFF框架,打通了Node到Java的RPC通信链路

Egg.js已经开源(Egg.js是以Koa作为基础框架),需要基于Egg.js去打造属于自己的BFF框架

RPC的意思是不在一个内存空间的两个应用,借助网络来实现,像调用本地的函数一样去调用远程函数

BFF不是银弹,有着自己的问题:

研发成本上升:前端团队既要开发客户端,又要开发BFF,人手不够
流程繁琐:BFF引入后,要同时走前端、服务端的研发流程,多端发布、互相依赖,导致流程繁琐
运维经验不足:主要是前端工程师运维经验不足(给业务团队带来了很大困扰)
尽管职责划分越来越清晰,但是由于前后端发布系统不一致,前端团队仍需要在基于不同的代码仓库进行研发,走不同的发布流程

理想的开发流程:

蚂蚁金服推出的解决方案TWA(Techless Web Application),是一个全栈的研发框架

TWA是为了提升开发者研发体验而推出的渐进式解决方案,开发者在一个代码仓库下,基于TWA的框架,完成客户端和BFF层的研发,通过Basement研发平台提供的流程支持,不用再关注应用、构建、部署、流程等细节,可以一键将应用部署到各个运行终端,同时在研发平台上完成应用的自主运维和监控

将TWA拆解开来,分为了三个大的方向:框架、研发平台、运行时

框架:提供了前后端合一的框架,通过定制化网关,抹平多个终端和接入形式的差异,让一套代码可以运行在不同的终端下(?)
研发平台:Basement,提供TWA的研发迭代、自主运维和监控,精简规范了H5 APP的研发流程
运行时:通过基础服务和Docker,给客户端代码和服务端代码提供稳定可靠的运行环境


框架
是一个渐进式框架,可以选择部分能力使用

客户端、服务端目录、依赖都是相互独立的。

复杂的终端环境,有不同的接入链路(可能通过网关走TCP长连接通信)、不同的鉴权方案。如果每个业务的BFF系统要对接到每个系统完成接入、鉴权是非常复杂的。

解决方案是:TWA网关层 + 客户端RPC Client,

TWA网关层统一完成所有终端的接入、鉴权,BFF不需要对接到每个终端,只需要对接到网关,让BFF接口统一

客户端的RPC Clinet是一个请求库,对接到网关,将客户端的鉴权、接入的细节隐藏,并且可以自动选择接入链路

这就可以在client目录下,像调用本地方法一样,调用server中目录下的服务

研发平台


Basement,一站式运维平台,基于Docker,支撑整个应用的研发流程,完成自动化的测试和部署

Node与Java的通信
与使用的微服务框架有关,可以采用HTTP的方式,也可以通过RPC调用。

蚂蚁金服的实践
数据:跨语言序列化协议hessian
服务:Node PRC
开源框架:

sofa-bolt-node:蚂蚁通讯协议Bolt的Nodejs实现
sofa-rpc-node:一个通用的Nodejs RPC模块
有赞的实践 – HTTP
可以采用服务注册中心:

首先,Java应用服务启动的时候,会往服务注册中心注册服务,这里的服务注册中心可能是ETCD或者Zookeeper,然后,Node应用在启动的时候,会先从服务注册中心拉取服务列表,接着Node会跟Java服务建立一条TCP长链接,除此之外,Node还需要负责Hession协议解析以及负载均衡等。

上面的方式Node职责比较重,对Node开发的要求高,有赞在此基础上做了改进:

在Node和Java之间添加了一层中间代理层Tether,Tether是用Go语言写的一个本地代理,Tether会对外暴露一个HTTP的服务,对Node来说,只需要通过HTTP方式调用本地的服务即可,其他服务化相关的服务发现、协议解析、负载均衡、长链建立维护都交由Tether来处理。这样,Node这一层就非常轻量了,Node是调用Java服务时:

const Service = require('../base/BaseService');

class GoodsService extends Service {
  /**
   * 根据商品 alias 获取商品详情
   * @param  {String} alias 商品 alias
   */
  async getGoodsDetailByAlias(alias) {
    const result = this.invoke(
      'com.youzan.ic.service.GoodsService',
      'getGoodsDetailByAlias',
      [alias]
    );
    return result;
  }
}
module.exports = GoodsService;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这种方式的优点:

使用简单,对前端开发非常友好,只需要通过HTTP方式调用本地的Tether服务即可;
多语言接入成本低,后期如果有其他语言(Python、Ruby)也需要接入整个服务化体系,也像Node一样,它们都只需要调用本地Tether暴露的HTTP服务即可,没有额外的开发成本了。
后期更方便做协议层的优化,因为这种方式Tether其实就是一个代理,后期如果需要做协议层性能上的优化,那只需要优化Tether的性能就可以了。
总结
关于TWA
TWA是蚂蚁金服自研的,整合了BFF的一整套渐进式的前端+Node聚合层的开发体系,它不仅包括了BFF的引入,还包括了前后端代码管理、部署、运维等功能框架。

但是很遗憾的是,TWA没有开源,对于想要从0开始引入BFF,想实现TWA的功能,还有一个努力的过程。

实际上我们引入BFF,不是要完整的开发TWA,而是首先实现Chari BFF的功能。

接入BFF的好处
对于团队来说:

业务支持变多
沟通协作变少
解决问题变快
对于个人来说:

更合理分工
做BFF可以拓展知识面
接入BFF的坏处:
组织决定了架构的复杂度
前期学习成本高,短期成为资源瓶颈
可能遇到的问题和可能的解决方法
Node与Java通信 – Hessian(数据),RPC(服务)(sofa-rpc-node)/ (grpc-node)
前端代码和BFF段代码管理 – Egg.js(同一个仓库,不同目录,不同依赖,分别打包、分别配置)
前端的应用发布、运维能力 – Docker
服务端的配合 – 服务:微服务(?),人员: (?)
前端能力提高 – 前端能力(JavaScript + HTML + CSS) + Node(服务端技能)+ Java(如何与Java通信)+ 运维能力(Docker)
参考
Pattern: Backends For Frontends@samnewman
为什么互联网公司开始用node.js做web服务的中间件?有什么好处吗?@知乎
Backend For Frontend@黯羽轻扬
蚂蚁财富的BFF实践.pdf@alipayobjects
微服务架构:BFF和网关是如何演化出来的@10条
Developer Experience First —— TWA 的理念与实践@知乎专栏
Techless Web Application 的理念与实践 — 不四@优酷
02_SEEConf_TWA的理念与实践_不四.pdf@语雀
Node 在有赞的实践@掘金
聊聊 Node.js RPC(一)— 协议@语雀
聊聊 Node.js RPC(二)— 服务发现@语雀
————————————————
版权声明:本文为CSDN博主「多拉斯基」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/duola8789/article/details/89332064

发布了44 篇原创文章 · 获赞 130 · 访问量 137万+

猜你喜欢

转载自blog.csdn.net/gb4215287/article/details/104764837