BFF在SoundCloud中的实践(翻译)_bff@soundcloud-程序员宅基地

技术标签: Java技术  BFF  android  soundcloud  backends  

说明

这是一篇我翻译的文章,原文出处是:

https://www.thoughtworks.com/insights/blog/bff-soundcloud

翻译的原因无他,就是觉得文章写得好。

名词解释

  • BFF,backends for frontends,它是一种架构技术,一般指在微服务架构中根据客户端的不同,对后端接口进行分类支撑

  • SoundCloud,音频分享服务平台,是一个为喜欢音乐和爱好声音记录生活的人士打造的分享平台,用户可以上传音乐和音频文件,通过音频时间轴标记留言并分享

  • Rails, 是一个使用 Ruby 语言写的开源 Web 开发框架

  • monolith,单体架构,相对于微服务架构

  • Finagle,一种微服务框架

  • strangler pattern,一种处理大型 Web 应用程序中的重构代码发布方式。Web 应用程序是通过将功能映射到业务领域的不同方面的 URL 来构建的 — 将应用程序拆分为不同的功能领域,并一次一个领域地将这些领域替换为基于微服务的新实现。

正文

我们几年前在SoundCloud的朋友开始了一次把他们的单体架构Rails应用微服务化的旅程。在该项目中,对他们来说特别有效的一件事是BFF模式,也就是backends for frontends。 他们在BFF的实践和背后的成功故事可能有助于其他团队; 所以我们决定把它写下来。 我们希望您觉得它很有用。

为什么改造

早期,SoundCloud是一个单体架构系统,公开了一套服务于Web客户端,Android和iOS应用程序以及互联网的API,里面各种混搭,协作等。这个共享API随着每个功能需求而不断增加,因为架构的原因这些改动贯穿整个平台和API的使用者。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-22ISzDQk-1572703807880)(https://insights-images.thoughtworks.com/BFF_18ab348d8f5e013b45101cd9ee27b01d.png)]

一段时间后,这种架构开始出现问题,无论是在添加新功能所需的时间方面,还是由于平台的不同需求。 例如,对于移动API,应该比web API更小的数据和请求频次。现有的单体架构API没有考虑到这一点,因为是另一个团队开发的,他们并不知道移动端的需求。 因此,每当应用程序增加一个新的访问点,首先前端团队要让后端确信这是真的需求,然后就是没完没了的沟通,开发的故事了。

问题很明显:不必要的摩擦,沟通开销和延迟。 与此同时,后端团队开始遇到单体架构带来的问题,因为添加新功能变得更加困难,同时bug修复的工作越来越多。

改造方案

为了解决这些问题,SoundCloud决定每当实现一个功能需要一个特定的,经过微调的API时,驱动它的团队也能够实现API端点,从而决定从哪里获取数据以及如何聚合它,什么有效载荷 需要传输等。此API端点将在整体应用程序之外创建,并充当特定于功能的接口。前端团队是这一层接口的所有者。

BFF诞生了,可以根据特定平台和功能(Android,iOS客户端,Web API和其他使用者)的需求进行调整。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3s2JCEUX-1572703807881)(https://insights-images.thoughtworks.com/BFF2_dda55fa4bab3599a8ff3911808b43bd3.png)]

前端开发者编写后端代码

这种转变意味着到目前为止主要依靠Android或iOS开发的主要专业知识来处理前端代码的人需要涉足后端:不同的技术栈和不同的挑战。 为了解决这个问题,后端团队开发了一个轻量级库,可以更轻松地编写“边缘服务”,这种服务是负责警报,监控,遥测,身份验证以及应用速率限制和清理传入请求的最佳实践。 这有助于标准化BFF的编写方式,因为它基于BFF框架更容易被使用(基于Finagle),而不是从头开始做所有事情。

BFF 作为迁移的一部分

BFF的一个特点是它消除了外部到下游服务的任何直接调用。此模式的实现还实现了向基于微服务的体系结构的最小侵入式迁移,因为BFF隐藏了应用程序本身的任何潜在变化。新功能通过BFF成为新的微服务或整体。每当从整体中提取更多功能时,BFF就会被更改,而应用程序代码保持不变。人们可以看到与strangler模式的相似性,其中BFF正在扼杀单体架构提供的公共API。因此,引入了名为public-api-strangler的BFF来隐藏消费者的整体API。它最初只是将请求转发给整体的代理。随着时间的推移,来自整体的部件被提取出来,而public-api-strangler只是将请求重新路由到新的微服务。消除对整体API的直接消费者调用,简化了向基于微服务的系统的迁移过程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sI9zMTUc-1572703807881)(https://insights-images.thoughtworks.com/One_or_more_BFFs_cf35965f5b900ae6d357e8a0a3ae7588.png)]

一个或者多个BFF

你应该选择多少个BFF? 在移动平台上,由于时间和资源有限,SoundCloud一开始iOS和Android使用一个BFF。 不过事后看来,为每个平台提供一个BFF会更好,因为Android和iOS应用程序的不同足以暴露不同的API需求。 您还可以考虑为每个平台提供一个BFF,如果两个平台上都存在特定功能,则可以使用相同的BFF。 SoundCloud用户可以分为创作者和听众; 因此,为创作者提供一个BFF,为听众提供一个BFF也是有意义的,因为这些用户组也可以获得单独的应用程序。 这是SoundCloud决定执行的思路。

人们可以尝试定义更细粒度的BFF,封装特定的功能,这将在BFF的发布周期上有更大的灵活性。但是,由于平台审核流程以及用户实际触发更新的意愿,应用程序发布周期更加“严格”,因此仍然与他们正在服务的应用程序紧密耦合,这部分是有争议的。

SoundCloud决定为每个上游用户创建一个BFF:它可能是一个服务于特定需求的应用程序(例如iOS监听器应用程序与iOS创建者应用程序)或用于嵌入式使用的API或面向Facebook,Twitter等战略合作伙伴的API。 BFF为不同需求带来的好处,特别是发布周期,足以证明这些努力的合理性。

目前,所有BFF都基于相同的核心库/框架(已在上面提到),每周发布时间表中更新。 共享BFF也有它的问题,例如:

  1. 过快地向库中添加新功能,而不是让它稳定应用在某些服务中,可能导致所有BFF升级到错误或不稳定接口的版本

  2. 允许足够的灵活性和可配置性,会让我们错误的认为默认实现适用于每个BFF

  3. 保持库尽量小并且可组合,因此开发人员可以根据自己的喜好选择部件

BFF的演化

现在SoundCloud的BFF显然随着时间的推移而增长。应用程序获得了新功能,它要求新的BFF功能。这种横向增长不会引起任何问题。但是BFF也在深度(垂直)上增长,并且暴露了一些重复的功能被提取到核心库中。 问题是哪些应该成为一个新的服务或库。指导规则是:如果要提取的功能不需要随时更新,则使用共享库,否则使用服务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkAH2lcS-1572703807881)(https://insights-images.thoughtworks.com/EvolutionofBFF_8003911266125f52d2bffca7ac16fac3.png)]

说到重复和复用,不要试图从一开始就使一切都变得通用。如果在整个组织中尝试这样,它将导致矛盾,因为很多人都想要贡献自己的想法。 考虑通用之前,请专注于您的功能和特定用例。 “通用的特殊功能优先”战略的效果要好得多。 在考虑提取代码时,不要忘记有用的“三规则”。

结论

BFF提供了一种很好的方法,使团队能够构建不同的面向客户端的应用程序来分而治之。这种自主权对于快速迭代客户端应用程序并快速提供良好的体验至关重要。 通过灵活的可变性,BFF支持快速迭代,并将整个系统变得更好,更低耦合,最终成为一套健壮的具有单一功能的API。

最后但并非最不重要的是,向SoundCloud的Kristof Adriaenssens,MatthiasKäppler和Michael England致敬,感谢BFF的故事以及对SoundCloud在微服务旅程中所有知识的分享。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pony_maggie/article/details/89791339

智能推荐

BootStrap3 下拉菜单dropdown_el-dropdown-menu 左对齐-程序员宅基地

文章浏览阅读969次。目录官方地址基本用法向上弹出菜单菜单项对齐左对齐带标题的下拉菜单带分割线的下拉菜单激活的菜单项禁用的菜单项整体代码官方地址https://v3.bootcss.com/components/#dropdowns基本用法.dropdown 声明下拉菜单组件button 声明触发器.dropdown-toggledata-toggle="dropdown"ul 声明菜单项...._el-dropdown-menu 左对齐

Andoid Studio-android开发03-点击按钮Button-在TextView上显示文本_android ui 让按钮显示在文本上层-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏41次。一、界面设计在activity的design模式下,从palette中拖曳三个TextView和一个Button到界面上在activity_main.xml中设置整体布局为:<LinearLayout ="http://schemas.android.com/apk/res/android"在设计模式下,拖动TextView和Button的边框,调整大小。对应的xml代码为:<?xml version="1.0" encoding=._android ui 让按钮显示在文本上层

PTA List Leaves(非链表题解)_list leaves 题解-程序员宅基地

文章浏览阅读219次。题目如下:7-4 List Leaves (25 分)Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.Input Specification:Each input file contains one test case. For each ca..._list leaves 题解

Ext JS中隐藏TextField 同时隐藏 Label的方法_ext.js 隐藏-程序员宅基地

文章浏览阅读2.8k次。Ext JS中调用TextField.hide()的时候文本框隐藏了,但是前面的label会留在那(其他控件也有这问题),很怪异,用下面的方法可以一起隐藏: 隐藏: Javascript代码 field.disable();// for validation field.getEl().up(.x-form-item).setDisplayed(false); // h_ext.js 隐藏

使用阿里巴巴开源项目easyexcel解决poi的oom问题_阿里巴巴 处理poi-程序员宅基地

文章浏览阅读6.8k次,点赞2次,收藏10次。easyexcel最新版本:1.1.2-beta4源码git地址:easyexcelmaven坐标:&lt;groupId&gt;com.alibaba&lt;/groupId&gt;&lt;artifactId&gt;easyexcel&lt;/artifactId&gt;&lt;version&gt;1.1.2-beta4&lt;/version&gt;一、定义Java模..._阿里巴巴 处理poi

7-2 输出各位数字之和能被15整除的所有数 (10分)C语言-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏16次。**7-2 输出各位数字之和能被15整除的所有数 (10分)**输出100到1000之间的各位数字之和能被15整除的所有数,输出时每5个一行,每个数输出占4列列宽。输出格式:在每行中输出5的满足要求的数值,每个数输出占4列列宽。输出样例:159 168 177 186 195249 258 267 276 285294 339 348 357 366375 384 393 429 438447 456 465 474 483492 519 528 537 546555 564 57_输出各位数字之和能被15整除的所有数

随便推点

@SpringBootApplication already applies given @ComponentScan-程序员宅基地

文章浏览阅读1.3w次,点赞2次,收藏11次。我在写一个feign的例子,在启动类中加上@ComponentScan下面有红线。提示内容为@SpringBootApplication already applies given @ComponentScan代码是根据尚硅谷课程里面写的,。看了源代码写的是一样的。https://www.bilibili.com/video/BV1HW411V7cr?p=37不知道哪里出了问题。不知道从哪个方向入手解决。..._already applies given

JPEG系列四 JPEG图像压缩优化_jpeg如何对量化表压缩率进行调整-程序员宅基地

文章浏览阅读5.7k次,点赞4次,收藏14次。JPEG中使用了量化、哈夫曼编码等,极大的压缩了图片占用的空间,那么是否可以进一步压缩呢?从技术角度讲,是可以的。如DropBox开源的lepton,在目前的JPEG压缩基础上,可以再节省22%左右的空间。lepton中使用算术编码(VP8)替换哈夫曼编码,以得到更高的压缩率。算术编码90年代已经出现,但是受限于专利,没有被广泛使用。同样由于专利限制没有广泛使用的还有gif中的压缩编码lzw。本篇介绍算术编码的基本原理和过程。_jpeg如何对量化表压缩率进行调整

Android 7.0以上时使用recycleview发现Item显示不全_as中recycleview的item排列有问题-程序员宅基地

文章浏览阅读2.7k次。 前几天项目终于到一个问题,API在23以上时候recycleview里面嵌套一个recycleview,它的item显示不全,最后找到其解决办法。如下为你的RecyclerView上再嵌套一层RelativeLayout然后添加属性 android:descendantFocusability="blocksDescendants",android:descendantFocusability..._as中recycleview的item排列有问题

Python爬虫:requests的headers该怎么填_爬虫headers怎么写-程序员宅基地

文章浏览阅读1.9w次,点赞30次,收藏88次。1、为什么要写headers?我们一般写的爬虫会默认向服务器发送爬取请求,而一般情况下网站是不允许被爬虫访问的,输出的text信息中会出现抱歉,无法访问等字眼。我们通过更改User-Agent字段则可以实现网站请求,实现网页应答。2、 headers该怎么找?最简单的步骤如下:打开你要爬虫的网页 按F12或通过浏览器右上角的“更多工具”选项选择【开发者工具】 按F5..._爬虫headers怎么写

关于ie8以上浏览器下—兼容性视图设置-程序员宅基地

文章浏览阅读3.4k次。近期开发遇到一个问题,在ie11上页面排版显示的凌乱不堪,后来发现是在浏览器的兼容性视图设置 这个应用中 添加了当前站点,去掉之后页面就显示正常了。 出于好奇,查询了一些关于这个功能的说明。原来兼容性视图设置项目,通过设置,可以让浏览器采用IE7.0的渲染模式,解决按照老版本浏览器要求开发的网页的错位和跑远等问题。也就是说为了兼容 在ie8之前老版本的ie浏览器的w

MD5加 秘钥 (数据加解密类 / 直接复制使用)_md5 secretkey-程序员宅基地

文章浏览阅读5.4k次。import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;public class AesUtil { private static fina..._md5 secretkey

推荐文章

热门文章

相关标签