在微服务体系结构中,客户端应用通常需要使用来自多个微服务的功能,在小型应用程序中,通常会使用客户端到微服务直接通信的方式:
在此种模式下,每个 Microservice 可能有一个不同的 TCP 端口,或者配置了不同的 URL 地址。
在一个基于微服务的小型应用程序中,它能基本满足,尤其是在客户端应用为服务器端 Web 应用程序(如 ASP.NET MVC 应用)的情况下。 但是,若要生成基于微服务的大型复杂应用程序(例如处理大量微服务类型),尤其是客户端应用是远程移动应用或 SPA Web 应用程序时,该方法将面临一些问题:
在 Sam NewMan 的一篇文章 Pattern: Backends For Frontends 中,最早提出 BFF 概念,认为 BFF 是复杂应用的自然产物。BFF 即是用户体验适配层,根据不同的设备类型,来返回不同的结果。
根据业务边界和客户端应用划分的 BFF 层,能提供诸如反向代理、接口聚会、裁剪等功能,除此之外,BFF 层的出现让领域模型与页面数据更好的解耦,让彼此更高效。
理想情况下,前端页面与 BFF 层由不同的同学开发,前端人员专注于页面数据;开发 BFF 的同学,则按需聚合、裁剪数据返回给前端。但是现实往往是 BFF 以及页面数据都由前端人员来开发,尤其是对于做中后台的系统来说,一个前端同学既要写复杂的业务逻辑,同时又负责 BFF 层的开发,久而久之,BFF 层的存在,退化到仅仅是一层代理,如同虚设。
我们也在寻找一种适合于我们自己业务模型的架构模式。
实践过后,我们决定去掉 BFF 层,而引入更为通用的从属于前端的 API 网关层(注:BFF 是 API 网关模式的一个特例):
在这个 API 网关层中,我们不再做数据的聚合与裁剪,因为这些对于一个中后台的内部系统来说,并不重要。
使用 API 网关,也着实解决了我们的一些痛点:
当然,我们也有一些 2C 的产品,这些产品中,有一部分我们是使用 Vue/React SSR 技术,
在这个 Vue/React SSR 中,一定程度上,也充当着 BFF 层的作用。
我们并没有使用传统的 Client->API网关->BFF->微服务 架构模式,面对特殊的业务场景(大量的中后台应用),我们取消了 BFF 层,使用了 Client->API网关->微服务,而对于 2C 的应用使用 Clent(SSR)->API网关->微服务 这样架构模式。
当然,我们也在尝试、探索基于 Serverless 的 Gateway 架构:
(图片来自:github.com/nodejh/node…
Serverless 在更多、更复杂领域的实践值得期待。