微服务架构模式:让自己对BFF层有个了解——服务于前端的后端

createh52个月前 (02-01)技术教程16

BFF用于前端的后端

◎ 回顾前后端分离发展史

◎ BFF诞生

◎ 基于RESTful的BFF

◎ 基于GraphQL的BFF

随着前端技术的大爆发,面对逐渐复杂化的前端工程体系,越来越多的企业开始采用前后端分离的开发模式。随着微服务模式的流行,前后端的交互也变得越来越复杂,大量接口的组合、复杂的配置、重复的代码等问题使前后端的开发者饱受折磨。于是,一个新的模式就此诞生:用于前端的后端。

回顾前后端分离发展史

为什么原来简单的开发模式会发展成如此复杂的模式呢?还是那句话,并不是分离就是好的,分离到底是对是错?它的意义是什么?想知道这些问题的答案,就要了解传统软件的开发模式是如何演进为如今前后端分离的开发模式的。

日渐臃肿的前端

10年前,浏览器还是属于IE的天下,前端开发只需一个JQuery即可,处理的无非是查找页面元素,注册click或change事件,然后将数据发送到服务端或是将服务端的数据填写到页面。Java开发者即使不会JQuery,他们也有JSP,各种el表达式用法灵活,还能自定义标签,虽然页面碎片化严重,结构不是十分严谨,但也能将项目开发出来。随着互联网的发展,传统的交互体验已经不能满足用户需求,高速的响应、复杂的交互、酷炫的动画效果、多设备的兼容等新的市场需求促使着前端开发承担越来越多的工作,前端的代码也就越来越多、越来越复杂、越来越难以维护。

虽然有一批类似Twitter开发的Bootstrap的前端框架,试图使用封装组件的方式提高前端工作的效率,但没过几年,Google推出第一版的AngularJS,这让当时还停留在努力学好JQuery的前端开发者眼前一亮。

双向数据绑定等新特性让前端程序员发现了新大陆,并受到AngularJS的启发,相继开发了大批MVVM的前端框架,其中不乏很多优秀的国产框架,如Avalon、KnockoutJS、Vue等,笔者也有幸经历了这个过程,甚至还主导了自己所负责的团队在新项目上采用AngularJS,其结果却不尽如人意,抛开使用新技术“踩坑”的时间,假设那时的AngularJS功能已经很完善,反观项目的代码,在早期时会显得特别清爽,大家开发效率也很高,质量也不错,但随着项目时间的推进,功能越来越多,需求越来越复杂,模板、自定义指令层出不穷,仿佛又回到了使用JQuery的时候。

随着各大公司在前端的投入越来越多,前端代码日渐臃肿,越来越难以维护,重复的工作天天要做,使得前端急需拥有像后端一样的工程化管理能力,甚至可以自动变异、打包和发布,于是ES6、Node.js等新一波前端技术革命出现了。

前端技术栈大爆发

这是一个技术浮躁的时代,前一个项目定好的技术方案到这个项目就过时了。但这是一个知识风暴的时代,互联网拉近了人与人之间的距离,大家的知识碰撞在一起,创造了各种新奇的事物,包括互联网本身,也在这场风暴中不断淬炼和洗礼,后端技术如此,前端技术也是如此。

之前提到了Node.js,这里不做赘述,它的出现为前端技术带来了工程化的管理、模块化的开发、组件化的复用等一系列的特性,从而引发了前端技术的大爆炸。例如,新一代的前端框架React、Angular和Vue,打包工具webpack等,以及现在主流的移动互联网技术,如HTML5、ionic等。根据不完全统计,目前的前端技术栈如图6.1所示。

前后端分离的必然性

早期我们探讨前后端分离的意义,更多的是在组织结构上将前后端的工作进行拆分,但随着前端工程逐步多样化、复杂化,程序员已经无法在充分考虑后端技术的同时,又能很好地掌握前端的技术,而且随着越来越多的后端服务化,前后端的界限越来越明显、职责越来越清晰,后端对前端的影响也越来越少。

于是各大公司开始成立专门的前端岗位,组件前端团队,他们学习和研发前端的技术,专注于研究不同设备的用户体验和兼容性,甚至有些公司开始创新和研发新的前端技术。这段时间,前后端程序员各自单飞,分离开发,相互合作,携手迈进了前后端程序员平等的时代。

纵观发展不难看出,随着技术的蓬勃发展,以及微服务的兴起,前后端分离是必然的。

分离后的挑战

前面介绍了前后端分离的原因,那么是不是分离后就能解决这些问题?前后端分离后,会不会又有什么新的困难?答案是肯定的,下面介绍前后端分离后会出现哪些新的挑战。我们假设前后端都是有经验的程序员,他们界限清晰、分工明确、合作默契,但还是会遇到不少问题。

首先,沟通问题,以前都是一个人的工作,自己从前端写到后端,现在由两个人或两个团队来做,人数的增加导致沟通的成本和复杂度递增,如果后端改动了API,忘记通知到前端,就会产生一系列的问题,所以才有了第4章的契约测试,这里不再赘述。

其次,虽然后端已经服务化,而且提供了各式各样的接口,但还是不能满足前端需求,而且出于网络开销和性能的考虑,有新需求到来时,如需要一个已知的几个接口的结果数据集合的接口,或者需要一个已知接口的结果的少许数据,还需要后端程序员反复开发新的接口,即使这些接口不需要过多的后台工作量,往往只需将之前的接口进行组装或数据过滤,但反复的开发、测试、构建和部署也需要时间,而且越是大型项目,过程会越长。

再次,随着后端服务越来越多,接口的调用需要更多的配置,前端程序员在完成前端工作的同时,还要关心各个服务的调用方式,管理各个服务的接口也成了一项巨大工作。

最后,虽然前后端的工作分离,代码也分开管理,但后端为了满足前端的接口需求,不得不受到前端的影响,这是有些危险的设计模式,因为前后端分离的本质就是为了让后端能更加关注服务的设计和业务逻辑的实现,前端更加关注数据展示和用户体验。通常情况下,页面的展示逻辑决定着前端接口的需求,而往往页面的设计会与后端业务模型的设计有不小的差距,如果经常受到前端接口的影响,那么设计出来的微服务结构肯定会有不少问题。

那么,这是否证明前后端分离本身是一个错误的决定?答案是否定的,之前已经分析过前后端分离的必然性,所以看起来我们需要一个新的思路,即一种更好的架构模式去适应变化、解决问题。

BFF诞生

带着上文的挑战,大家开始探索一种新的模式。于是一项新的发明产生,用于前端的后端,这就是我们通常说的BFF(Backend For Frontend),其实严格来讲也不能算是发明,应该说是一种新的模式,而这种模式就是为了解决微服务模式下前后端的交互问题而产生的,下面将详细介绍BFF的作用及具体的设计和技术实践。

BFF的概念

BFF就是用于前端的后端,是为前端服务的,但它能解决不少后端的问题。例如,它可以组合或过滤各个接口,既可以解决过多的网络开销带来的性能问题,也能防止后端的设计受到前端的影响,同时前端页面也不会受到后台服务设计的影响,在前后端之间构建了一堵隔离墙。

BFF的概念首先由Sam Newman提出,他曾在ThoughtWorks工作了12年,致力于研究微服务设计和咨询工作,他是这么定义BFF的:BFF是一个面向用户界面和外部团体的单边服务。这个定义有两个重要信息:首先,BFF面向用户界面和外部团体,也就是给前端或外部调用;其次,BFF是一个单边服务。单边服务就是说这个服务只是一方调用,而另一方不会调用,显然BFF是给客户端使用的,服务端并不会调用它,BFF调用关系如图6.2所示。

由图6.2可知,BFF有一个关键的能力,就是组合接口,客户端不需要关心后端的多个服务,而只用和BFF进行交互,由BFF来完成接口的组合或转发,解决之前所说的前端需要维护多个服务调用信息的问题。

基础的后端微服务接口返回的是和系统的模型设计相关的数据,在前端的需求中数据的展示复杂多变,不同页面可能数据字段、结构都不一样。例如,有的页面是“丰满”的树状结构,有的页面是“扁平”的列表结构,这些数据结构不应该出现在后端的微服务中,这样后端服务会受到前端页面设计的污染,而且根据不同的终端,服务层会开发很多冗余的接口,所以BFF还负责对数据的转换和过滤工作,如图6.3所示。

在图6.3中,前端的需求多变,而且交互和体验的设计需要数据存在不同的结构,BFF可以隔离前后端的相互影响,让前端可以无约束地专注于设计,让后端也只需专注于模型,所有的过滤和转换都在BFF层中完成。

综上所述,BFF的功能大致总结如下。

(1)接口转发。

(2)接口组合。

(3)数据过滤。

(4)数据转换。

BFF的适用场景

在大部分微服务模式下都推荐使用BFF,哪怕项目再小,只要不能确定它是否有一天会出现更多的需求,或者会越做越大,都推荐使用BFF。尤其是当项目有多个终端,如手机和桌面,或者PC浏览器,这时使用BFF最合适了。不同的终端有着不同的展示逻辑,单纯的服务无法满足所有终端的数据需求,如果把这些事情都下沉到服务来处理,服务会显得特别臃肿。在我们大量使用微服务时,终端的页面逻辑在每个服务上都要实现一次或多次,BFF能有效分割前后端的相互影响,为前端单独提供统一的接口服务。

例如,如果使用契约测试保证后端接口可用,设想在一个没有BFF的微服务系统中,你需要定义多少个契约,对于每个后端微服务来讲,可能需要定义多个终端的契约,这个契约数量虽然多,但分散在各个微服务上勉强可以接受,但对于一个终端来讲,要定义的契约数量很多,且难以维护。

这时,如果我们使用BFF,一切就简单了,首先BFF是后端开发,对后端的接口调用会很熟悉,对于前端而言,只需与BFF定义契约即可,简单方便。

BFF模式

设计BFF最简单的方法是直接构建一个统一的服务,由这个服务去调用后端的服务,再提供API给所有的终端调用,如图6.4所示。

如果不同的页面或终端要进行相同或类似的调用,这种设计会很成功。实际上,随着移动技术的发展,移动端体验与桌面端或其他终端在界面上不同,所以这个设计并不能满足真实场景的需求。

既然BFF用于服务前端,设计上肯定要考虑前端的问题,其做法也很简单,我们根据界面的需求来划分,增加BFF的数量,针对不同的终端提供不同的BFF服务,其标准设计如图6.5所示。

我们在设计微服务架构时,会将BFF与API网关对应起来,即一个API网关对应一个BFF,BFF为每个API网关提供单独的接口服务,甚至在很多时候,把BFF和API网关放在同一个进程中,这样可以减少API网关对BFF远程调用的成本,而且是一对一存在。有人认为,BFF本身就是API Gateway的变种,二者组合使用如图6.6所示。

BFF其实就是API网关的另一种实现模式,只不过API网关更加关注身份认证、统一路由等功能,而BFF更加关注统一接口协议,构建更好的接口服务于前端。我们现在已经明白了BFF的设计初衷及BFF的架构模式,那么该如何实现呢?请听下文揭晓~

本文给大家讲解的内容是BFF用于前端的后端

  1. 下篇文章给大家讲解的是基于RESTful的BFF
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!

相关文章

推荐几个好用Redis图形化客户端工具

RedisPlushttps://gitee.com/MaxBill/RedisPlus RedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows 、Linux...

学习必备|分布式即时通讯服务端java版附源码

今日推荐:分布式即时通讯服务端推荐一款基于java开发的分布式即时通讯服务端,网络基于netty,akka实现实时信息,提供简单的API服务 ,方便二次开发。特点:1、支持单击部署,也支持集群部署2、...

拒绝接口裸奔!开放API接口签名验证

接口安全问题请求身份是否合法?请求参数是否被篡改?请求是否唯一?AccessKey&SecretKey (开放平台)请求身份为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(...

Java 中的 Http 客户端 API:身份验证

.介绍在本系列的第一部分(链接此处)中,介绍了 java http 客户端 API 的基本功能。现在我们将探讨当今应用程序中广泛使用的一些更常见的用例。我们将学习如何通过提供凭据来访问安全端点。基本认...

BsinCopilot:Java版端到端大语言模型开发框架

BsinCopilot是基于BsinPaaS开源框架构建的大语言模型应用SaaS服务,借鉴langchain的框架思想,引入 langchian4j组件,微前端微服务的架构设计,可快速助您构建和体验...