BFF — Backends For Frontends 。在后来的学习和工作经验累积中逐步的加深了对 BFF 的理解,这个模式它具有更加确切的一些使用场景以及解决的是一些更加特定的问题。本篇小作文中,从找到 BFF 的起源开始,回到 BFF 模式诞生的大背景下,去探索那个特殊环境下遇到了什么样的问题催生出了这个在微服务系统中出镜率极高的模式。
寻找源头
首先,从技术雷达(https://www.thoughtworks.com/radar/techniques/bff-backend-for-frontends)中 BFF 的条目上,可以找到一些蛛丝马迹。条目的发布时间是 2015 年 11 月10 日。接着,我们在谷歌搜索关键字Backend for Frontend 以及将时间范围限定在 2015 年 1 月 1 日到 2015 年 11 月 10 日。
接下来,对比搜索结果的时间,我找到最早出现 Backend for Frontend 词条的文章(https://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern_bff.html)。
文中提到,BFF 这个名字是被当时团队 TechLeader Nick Fisher(https://twitter.com/spadgos)提出的,并最后在团队投票后被采纳。为了万无一失,找到其他的交叉证据,我才能更加确定这个结果。非常幸运的是,在洞见文章(https://www.thoughtworks.com/insights/blog/bff-soundcloud)也提到了相同的结论。由此,我们可以说 BFF 模式是在 SoundCloud(https://zh.wikipedia.org/zh-hans/SoundCloud) 首次出现。接着,让我们一起回到BFF 第一次发挥威力的现场吧。
问题初现
为了更有条理的了解当年SoundCloud 遇到了什么样的挑战,我通过分类分项的方式来列举情况和分析。
-
背景:
-
SoundCloud(https://blog.sellfy.com/make-more-money-on-soundcloud/)
主要是通过付费订阅与广告进行盈利(也就是说,越多的曝光渠道,会给SoundCloud 带来更多的盈利机会) -
SoundCloud 是一个单体系统,通过暴露共享 API 的方式为 Web 客户端、Android 和 iOS 应用程序以及互联网、合作伙伴等提供服务。这些共享 API 随着功能和特性一起增长,最终变成了平台与客户端之间的集成点。
-
将 2007 年开始运行的 SoundCloud 从单体模式转变至微服务模式 (具体改造过程:https://philcalcado.com/2015/09/08/how_we_ended_up_with_microservices.html)。
此时,单体服务已经被拆分为多个微服务。 -
支持在 IOS 平台上新增的应用程序(原来的产品主要是在 Web 端提供服务)
Public.png
-
- 主要动机:
- 减少产品发布上线的时间
- 支持 IOS 平台的新应用程序,隔离其不同用户体验和交互模式带来的风险
-
挑战:
-
为了让第三方开发人员能更自由的集成,需要设计出不对数据的使用方式做出任何假设的 API。 所以,即便是呈现很简单的体验,也需要许多的 HTTP API 来提供服务。导致了构建一个简单的页面的数据需要上百个 API 请求来获取。
-
每次团队需要更改现有API 时,都需要确保更改不会破坏我们现有的任何客户端(包括重要的第三方集成)。每当添加新内容,都必须投入大量时间来确保新功能不会过度用于特定客户端,以便所有客户都可以轻松使用新功能。 所有这些协调使日常工作变得比应有的困难得多,也就导致了新功能发布缓慢。
-
开始准备开发新 iOS 应用程序, 新平台上的应用程序的用户体验会全部被重塑
通过分析上面的各种情况,可以得出当时SoundCloud 后端团队面对的如下几个问题:
-
-
问题一:难以为每个第三方客户提供合适粒度的 API,导致了 API 数据粒度过细,想完成一个业务服务需要请求的 API 太多。
-
问题二:现有的对外 API 与消费方耦合严重,维护成本高,时间长,新功能发布缓慢。
-
问题三:IOS平台新客户端更进了用户体验和交互方式,需要隔离新App带来的风险,并且还要找到与多个客户端团队更好的合作方式。
看上去,这三个问题在通常后端团队在完成微服务改造中往往也会遇到。让我们一起看看,他们是如何一步步见招拆招解决问题,并且找到《BFF》这个内功心法的。
Backends For Frontends 初成
SoundCloud 后端团队在面对上面复杂的问题时显得非常的专业。他们一开始便决定了,通过对不同客户端提供不同的 API 来各个击破。避免重蹈覆辙,多个客户端依赖同一套 API,继而耦合需求重合,无法进行灵活变更。同时,后端 Tech Lead Nick Fisher 创造了 BFF 这个缩写,也在团队内通过投票被认可。BFF 终于出现在技术世界的舞台之上,当时的架构如下图所示。
ServceB.png
你会发现与现在使用 BFF 模式的架构图有些细微的差别。没错,现在 BFF 还没真正的进化到成熟模式。接下来让我们看看它是在什么契机之下发生了进化。
后续的的研发中客户端团队意识到。由于他们拥有 API, 他们可以提取对不同服务进行多次调用的所有逻辑,并将它们混合到后端的用户配置文件中。这将简化代码并提高性能。不是对后端服务多次不同的调用,而是客户端对单个资源简单请求,例如:
-
GET /user-profile/123.json
当后端团队进一步试验这个方式时,他们发现了自己在 BFF 中编写了很多 Presentation Model。 在这个时候,他们突然意识到 BFF 不只是被客户端使用的 API ,而是 BFF 本身就是申请的一部分。BFF 新的形态出现了,具体如下图所示:
滴答滴答,时钟在前进,SoundCloud 的 BFF 也在持续增加。这时,他们已经在生产环境同时维护着 5 个 BFF 了。为了进一步提高生产力,减少不必要的重复。 User Profile 从每个不同的微服务中抽取出来,变成一个独立的在 service 与 BFF 之间的应用服务。随着时间的推移,他们发现了越来越多这样的情况。现在 SoundCloud 的 BFF 显然随着时间的推移而增长,这种横向增长再不会引起任何问题了。最终,BFF 模式的架构变成下图:
Serviee A.png结论
BFF 模式为我们在使用微服务时,针对多客户端开发的问题,提供了一种很好的方法。使我们在构建面向客户端的后端团队能够掌控自己的命运。 这种自主性对于快速迭代客户端应用程序并快速提供良好的体验至关重要。 通过支持持续的演进和变化,通过这种模式可以将消费者的行为限制在一个可控范围,会使他们变的更容易合作和改变。并且,更好满足不同客户端不同的特性需求。如果,在系统建立一开始便希望所有东西都是可复用的,会给系统的维护和协调带来巨大的挑战。特别是在面对需要维护多个客户端或消费者的场景下。在考虑通用用法之前,请专注于您的功能和特定用例。再在了解情况的基础上逐步进行低成本和合理的通用和复用。
网友评论