BFF — Backend For Frontends,经典分布式架构设计模式之一。我在学习和工作经验累积中,逐渐加深了对 BFF 的理解。作为一种模式,它具有一些更加确切的使用场景,和一些能匹配的特定问题。
在本篇文章中,你们会与我一起穿越回BFF诞生的历史中,寻找其起源。并一同探索和学习这个在分布式系统中出镜率极高的架构模式。
在毫无头绪的情况下,我们可以首先从Thoughtworks技术雷达中 BFF 的条目入手,去找到一些历史的蛛丝马迹。BFF 条目的发布时间是在 2015 年 11 月10 日。从这个信息我们可以获知,BFF 在历史崭露头角应该是在 2015 年 。
紧接着,在谷歌搜索关键字Backend for Frontends 以及将时间范围限定在 2015 年 1 月 1 日到 2015 年 11 月 10 日。通过对比搜索结果的时间,我们可以轻易发现最早出现 Backend for Frontends 词条的文章。文中提到,BFF 这个名字是由当时团队 Tech Leader Nick Fisher首次提出,通过投票获得了内部团队的认可。好了,我们现在获得了一个非常具体的证据。作为严谨的技术工作者,我们找到其他的交叉证据,提高这个结论的置信度。
非常幸运的是,在另一篇2015 年的 Thoughtworks 洞见文章中也提到了与上面证据相同的内容。终于,我们可以说 BFF 模式是在解决 SoundCloud的分布式系统问题中首次出现。下面,让我们一起回到BFF第一次发挥威力的现场吧。
为了能让大家更容易了解到SoundCloud 当年究竟遇到了什么样的挑战,我会在下面通过分类分项来列举情况以及进行分析。
背景:
主要动机:
挑战:
通过分析上面的各种情况,可以得出当时SoundCloud 后端团队面对如下几个问题:
这三个问题在后端团队进行微服务改造中往往也会遇到。让我们一起看看,当年的 SoundCloud 团队在面临同样的问题时,是如何一步步见招拆招,摸索出 BFF模式 这个内功心法的。
接下来,BFF 模式演进这一分是由客户端团队获得的。由于他们是 API 的消费者, 可以将不同服务进行多次逻辑调用,混合到后端的用户配置(UserProfile)文件中。这样避免了对后端服务多次不同的调用,实现客户端对单个资源的简单请求。这将简化客户端代码并提高整体性能,例如:
后端团队接受了这个逻辑,并开始试验这个方式。他们在 BFF 中编写了很多 Presentation Model。 在完成一部分任务后,后端团队突然意识到 BFF 不只是被客户端使用的 API ,它本身就是申请的一部分。BFF 新的形态出现了,具体如下图所示:
随着时间推移,SoundCloud 的 BFF 也在增加。他们已经在生产环境同时维护着 5 个 BFF 了。为了进一步提高生产力,减少不必要的重复。 用户配置(User Profile) 被从每个不同的微服务中抽取出来,变成一个独立的在 Services 与 BFF 之间的应用服务(Application Service)。
SoundCloud 的 BFF 依然随着时间在横向增长,不同的是这种横向增长不会再引起任何问题了。最终,BFF 模式的架构演变成与我们现在使用的几乎一致了。架构如下图:
我们在维护和使用分布式架构,同时面对多客户端时,BFF 模式提供了一种很好的架构模式,使后端团队在构建面向客户端的复杂需求时,能够掌控自己的命运。 并且,这种自主性对于快速迭代的客户端应用程序,能够提供快速而良好的体验。 通过支持持续的演进和变化,这种模式可以将相同变化趋势的消费者行为,限制在一个可控范围内。使他们变得更容易合作和改变,并且更好满足不同客户端的特性需求。
在系统架构中,因为离需求频繁变化的前端比较近(网络和组织架构上),BFF很容易野蛮生长,成为各种“妥协”的自留地,在使用的过程中,我们需要明确架构中各层相关的职能和边界。同时,如果确实有不得不去做的一些“妥协”,我们也一定要用技术债的方式,继续跟踪和管理,避免“妥协”越来越多以后,BFF从一个解决不同变化速率和需求的适配器,变成分布式单体的一个转化器。
我们往往会在系统设计之初犯下一个错误,那便是希望所有东西在一开始都是可复用的。这种思路会给系统后续的开发和维护带来巨大的挑战,挑战可能是来自应用间的协调,也可能是兼顾复用带来的高工作量。特别是在维护多个客户端或消费者的场景下会带来更大的困难。我们应该在考虑通用用法之前,先专注于功能和特定用例。在了解系统现状的主次和具体情况后,再针对性地区分需要通用和特殊处理的部分。这种系统设计和开发的思路和方式,使我们能够拥抱变化,立于演进的不败之地。
文/Thoughtworks 黄逸偲
原文链接:BFF的由来-Thoughtworks洞见