架構設計系列-前端模式的後端(BFF)翻譯PhilCalçado

本文翻譯自PhilCalçado的官網:https://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern_bff.htmlhtml

對咱們的架構演變保持透明是咱們技術戰略的一部分。咱們在無數場合談過的但從未真正詳細描述過的東西是咱們應用後端用於前端架構模式或BFF。這篇文章記錄了我對如何開發和應用這種技術的理解。前端

我對軟件組件演變的理解

在徹底分佈式架構變得可行以前,組織一般會在一個或多個層中構建應用程序層是應用程序的高度耦合但至關獨立的組件。加上在這,而不是服務,它被認爲僅由一個應用程序使用的感受。獨立於如何不做爲同一過程的一部分運行,甚至一般不在同一臺機器中運行。web

讓咱們用三個虛構的應用來講明這一點,當時任何大公司都會發展出來:json

這些體系結構可能變得很是複雜,但整體而言,在不一樣的應用程序之間繪製線條很是容易,清楚地劃分出一個開始和另外一個結束的位置。後端

當時,每一個應用程序都有本身的數據副本和重複的常見業務流程實現。隨着時間的推移,隨着組織得到或構建愈來愈多的應用程序,咱們意識到咱們須要不一樣的東西。咱們須要應用程序來共享數據和重用邏輯,而咱們曾經簡單的架構變得有點複雜:瀏覽器

隨着對更多重用和整合的需求,軟件行業的集體思惟方式決定了一個很是抽象的概念,稱爲服務實際上,這意味着上面的圖表改成相似於此的東西:網絡

上述架構的賣點是這些可重用服務提供的靈活性。理論上,在這個平臺上構建應用程序如今是一個問題:架構

  1. 選擇您須要的服務
  2. 寫一些調用這些服務的膠水代碼
  3. 將從中得到的數據合併到最終用戶更熟悉的內容中
  4. 以最終用戶可使用的方式呈現此數據

與此同時,計算機和互聯網正變得愈來愈流行。過去與職員或系統操做員交互的客戶開始直接與應用程序自己交互。設計思惟和用戶體驗研究使咱們擺脫了複雜的用戶界面,專一於讓專家用戶更高效地得到更豐富,更實用的體驗,客戶能夠理解這些體驗 - 沒有人閱讀網站手冊。更豐富的經驗須要豐富的數據,這意味着彙總來自各類來源的信息。app

按照咱們的示例,咱們最終會獲得以下圖所示的內容。iphone

咱們再也不擁有業務線系統的用戶界面,而是愈來愈多的用戶界面自己就是應用程序。這些應用程序一般用JSP,PHP或ASP編寫,其代碼包含用戶界面和特定於應用程序的後端邏輯。

打破巨石

上面簡單的例子與許多現代技術組織的架構發展方式沒有什麼不一樣。2011年,SoundCloud的網站以下所示:

Logic和All邏輯在一個地方。一個系統,而這個系統是應用程序。

前一篇文章所述,咱們發現此架構存在許多問題,並決定將邏輯提取到微服務中。儘管咱們在提取後端服務方面取得了成功,但最長時間內母艦仍然處於每一個請求的關鍵路徑上。

咱們正在進行的架構改變背後的主要動機是縮短新功能的上市時間,咱們發現咱們最糟糕的瓶頸在於任何須須觸及總體的變化。考慮到用戶界面更改的頻率,從總體中提取代碼是一種提升生產力的直觀方法。而後,咱們在其本身的組件中提取了咱們的UI層,並使其從咱們的公共API中獲取數據:

早在2011年,當這些架構發生變化時,絕大多數用戶都在網上。正如Fred Wilson所預測的那樣,最終這種狀況發生了變化,咱們的用戶羣開始使用移動應用程序的方式比Web界面更頻繁。SoundCloud已經爲Android和iOS提供了很長時間的移動客戶端,與咱們的新Web應用程序相似,他們直接與咱們的公共API進行了對話。

dogfooding帶來的挑戰

在現代軟件工程中,狗食一般被認爲是一件好事。在咱們本身的API之上構建咱們的產品被認爲是確保咱們的API具備高質量而且始終是最新的最佳方式。在實踐中,咱們遇到了這種方法的幾個問題。

咱們的第一個問題不必定與技術有關,而是產品開發的根本挑戰。若是咱們僅使用公共API,那麼咱們的平臺中沒有任何內容可供第三方API客戶端使用。儘管咱們想要一個蓬勃發展的SoundCloud集成生態系統,但咱們仍是一家廣告公司,所以咱們須要確保人們使用咱們的屬性,而不只僅是咱們的數據。建立咱們本身的應用程序獨有的功能意味着咱們必須在許多地方不斷檢查OAuth範圍,並令人們很難欺騙咱們的「官方應用程序」密鑰。

在一個更技術性的問題上,咱們的公共API幾乎按照定義是很是通用的。爲了使第三方開發人員可以構建有趣的集成,您須要設計一個不會假設數據將如何使用的API。這會產生很是細粒度的端點,而後須要對多個不一樣端點的大量HTTP請求才能呈現最簡單的體驗。您能夠在下面看到咱們過去在總體時代提出的請求數量與咱們爲新的Web應用程序生成的請求數量:

要生成該單個配置文件頁面,咱們必須對不一樣的API端點進行屢次調用,例如:

  • GET /tracks/1234.json (該曲目的做者)
  • GET /tracks/1234/related.json (推薦相關的曲目)
  • GET /users/86762.json (關於該曲目的做者的信息)
  • GET /users/me.json (有關當前用戶的信息)
  • ...

...而後,Web應用程序將合併以建立用戶配置文件頁面。雖然這個問題存在於全部平臺上,但對於咱們不斷增加的移動用戶羣來講,狀況更糟,由於他們常用不可靠且速度慢的無線網絡

咱們在上面的體系結構中遇到的第三個甚至更煩人的問題是,即便沒有總體結構,咱們仍然存在API的瓶頸。每當團隊須要更改現有端點時,咱們都須要確保更改不會破壞任何現有客戶端(包括重要的第三方集成)。每當咱們添加新內容時,咱們都須要投入大量時間來確保新端點不會過分專用於特定應用,全部客戶均可以輕鬆使用它們。全部這些協調使咱們的平常工做變得比應有的困難,並使咱們幾乎不可能進行A / B測試並減慢新功能的推出。

前端模式的後端(BFF)

在上述架構首次亮相近一年後,咱們開始準備開發新的iOS應用程序這是一個龐大的項目,最終會改變全部房產的用戶體驗。如此高風險,開發過程當中的實驗和迭代相當重要。當工程團隊開始考慮應用程序的體系結構時,咱們發現上述挑戰將成爲項目的阻礙,咱們須要從新思考咱們的工做方式。

咱們首先提出的解決方案是爲移動和網絡提供不一樣的API。咱們的想法是,讓客戶擁有API的團隊可讓他們更快地移動,由於它不須要部件之間的協調。咱們最初的想法是爲不一樣的前端設置不一樣的後端BFF一詞是由咱們的網絡技術主管Nick Fisher創造的(我最初的建議是BEFFE,但咱們講荷蘭語的隊友否決了這個選項)。

在它的第一個版本中,這些後端看起來仍然看起來像公共API,許多通用端點須要來自客戶端的許多調用來呈現單個屏幕。可是,隨着時間的推移,咱們發現了一些有趣的事情。以用戶配置文件頁面爲例,之前這是一個僅存在於客戶端的概念。Web或移動應用程序將從各個端點獲取數據,並使用它來建立咱們稱爲用戶配置文件的對象。這是一個特定應用程序的對象。

在某些時候,咱們的客戶團隊意識到,因爲他們擁有API,他們能夠將這個對象推向API。他們能夠提取全部調用不一樣服務的邏輯,並將它們一塊兒混合到後端的用戶配置文件中。

這最終將簡化代碼並提升性能。不是對上面描述的多個端點進行多個不一樣的調用,而是須要請求的全部客戶端都是單個資源:

  • GET /user-profile/123.json

當咱們進一步嘗試這個模型時,咱們發現本身在BFF中編寫了不少演示模型在這個階段,咱們意識到BFF不是應用程序使用的API BFF是申請的一部分。

最終,咱們的全部屬性(包括API)都開始遵循此模式。

一直往下

在某些時候,咱們生產了大約五種不一樣的BFF,咱們已經開始研究如何進一步提升生產率。接下來是咱們的用戶配置文件示例,對咱們來講顯而易見的是,鑑於每一個應用程序都有一個等效的用戶配置文件頁面,全部BFF都有不少重複的代碼來獲取和合並它們的數據。

複製並不許確,像網絡瀏覽器這樣的大屏幕在其用戶我的資料頁面上的信息要比微型移動應用程序多得多。然而,咱們看到重複是一種難聞的氣味,代表咱們在域模型中缺乏一個對象。爲了解決這個問題,咱們建立了一個UserProfileService處理這個重複邏輯的方法。

隨着時間的推移,咱們發現了愈來愈多這樣的狀況。咱們開始有意識地轉向一個架構,在這個架構中,用戶理解的大多數核心對象都有本身的微服務支持它們。

相關文章
相關標籤/搜索