零.背景
サーバー側が複数のフロントエンドデバイスにおけるユーザーエクスペリエンスをサポートする必要がある場合、しばしば既存の API と某一端の UI が緊密に結合している状況に直面します
例えば PC 端ページ向けに設計された API がモバイル端をサポートする必要がある場合、既存のインターフェースは設計から実装までデスクトップ UI 表示ニーズと強く関連しており、モバイル端の表示ニーズに簡単には適応できません
一.現状
1 つのバックエンド API 層が複数のフロントエンド(PC 端、モバイル端など)に対応する場合、一般的には一��をサポートした後、さらに機能を追加して其它の端をサポートします
It's tempting to design a single back-end API to support all clients with a reusable API.
複数のフロントエンド UI が要求する API が類似している場合、このようにしても問題ありません(既存の API を少し強化すれば別のフロントエンドエクスペリエンスをサポートできます)が、モバイル端 UI エクスペリエンスは通常 PC 端とは異なります
Valuable services support many variations in clients, such as mobile versus web and different forms of web interface.
例えば:
-
画面スペースが小さく、表示できるデータも少ない
-
複数の接続を確立すると電力消費が増加し、フロントエンドでのデータ集約コストが高い
-
インタラクション方式の差異が大きく、バックエンド API がサポートする機能も異なります。例えば PC 端ではフォーム入力、モバイル端では QR コードスキャン……
したがって、モバイル端では通常:
-
異なる(またはより少ない)API 呼び出しを行う。例えば集約など
-
異なる(またはより少量の)データを表示する
さらに、1 つのバックエンド API は通常複数のフロントエンドアプリケーションをサポートする必要があり、この場合単一のバックエンドがバージョンイテレーションのボトルネックになる可能性があります。各バージョンの作業量が膨大(N 個のフロントエンドアプリケーションと連携)であるためです。これにより庞大な独立したバックエンドチームが生まれ、複数のフロントエンドチームに API を提供し、各フロントエンドチームはそのチームと変更を調整する必要があり、そのチームは複数のフロントエンドチームのニーズの優先順位をバランスする必要があります……继而クロスチームコラボレーションの非効率性、リソース調整の困難などの問題に直面します
二.BFF の由来
以上の种种により、私たちは 1 つの大きなバックエンドが複数の端のエクスペリエンスに統一して API サポートを提供することを期待するのではなく、各ユーザーエクスペリエンスに対応する 1 つのバックエンド(one backend per user experience)を与え、Backend For Frontend (BFF) と呼び、ユーザーエクスペリエンス適応層と訳します
Consequently it's often best to define different back-end services for each kind of front-end client.
概念的に、各フロントエンドアプリケーションを 2 つの部分に分割します:クライアントアプリケーションとサーバー側の部分(BFF)。その中で、BFF は特定のユーザーエクスペリエンス面向であり、这部分の UI を実装するフロントエンドチームが実装および保守を担当します(つまり UI と対応する BFF は同じチームが担当)
These back ends should be developed by teams aligned with each front end to ensure that each back end properly meets the needs of its client.
同じチームである利点は:
-
UI に基づいて API を定義または調整しやすい
-
クライアント、サーバー側のリリースプロセスを簡素化(依存項が少なくなる)
-
1 つの BFF は 1 つの UI のみに焦点を当て、より小さくより柔軟
サービスの観点から見ると、BFF は実際には単一サービスがサポートする消費者(フロントエンドアプリケーションを指す)の数を制限し、それらをより使いやすく(フロントエンドのニーズに適合)変更しやすくし、フロントエンドアプリケーションを開発するチームにより多くの自主権を保持させます:
The simple act of limiting the number of consumers they support makes them much easier to work with and change, and helps teams developing customer-facing applications retain more autonomy.
三.具体的な実装
BFF とユーザーエクスペリエンスを一対一で要求する、つまり 1 つの大きなバックエンドを複数の小さなバックエンドに分割する必要があります
細分粒度
分割する必要があるなら、何に基づいて分割すべきか?どの程度まで細分化すべきか?
3 つの分割方式が考えられます:
-
ユーザーエクスペリエンスレベル(UI レベル):各 UI インタラクションに対応する 1 つの BFF。例えば PC 端 1 つ、モバイル端 3 つ(例えば小画面スマホ、中画面スマホ、大画面スマホの 3 つの UI インタラクションの差異が大きい場合、3 つの BFF に分割する必要がある)
-
端レベル:各フロントエンドデバイスに対応する 1 つの BFF。例えば PC、Android、iOS、時計、車載機など
-
チームレベル:各フロントエンドチームに対応する 1 つの BFF。既存の組織構造に基づいて分割
ユーザーエクスペリエンスレベルの分割を推奨します。端レベルの分割では複数の端の UI が類似している場合、インターフェースはおそらく直接再利用できるため、分割する必要がなく、組織構造は柔軟に調整できるため、技術方案を制限すべきではないからです
下流サービス(マイクロサービス)との連携
各 BFF は複数の下流サービスと連携する必要があるため、必然的にいくつかの問題が存在します:
-
技術スタックが異なる複数の下流サービスとどのように連携するか?
-
これらの呼び出しをどのように管理、どのように組み合わせるか?
-
某呼び出しが失敗した時、どのように可用性を保障するか?
統一された RPC プロトコルは下流サービスの技術スタックの差異を平らにできます。非同期呼び出しの管理については、RxJava、Finagle などのイベントメカニズムを利用してこれらの非同期フロー制御を簡素化できます。一部の呼び出しが失敗した時の可用性の問題は、BFF 層でフォールトトレランスを行い、同時にフロントエンドが不完全なレスポンス内容を受け入れられることを保証することで解決できます
再利用問題
分割した後、複数の BFF の間で冗長コードが発生しやすくなります。特に一部の共通のバックエンドロジック(認証、認可、レート制限など)
BFF 間のコード冗長を消除するために、一般的に 2 つの方法が採用されます:
-
複数の BFF を 1 つに統合
-
BFF の上に Edge API service を追加
複数の BFF を 1 つに統合すると、最初の問題に戻ります。柔軟性を求めて分割したのに、再利用を求めて統合する……無駄な労力です。もう 1 つのオプションは*ゲートウェイサービス(Edge API service)*を追加し、共通ロジックを入れて、BFF がビジネスロジックに集中できるようにします:
It validates and authenticates incoming requests; it enforces rate limits to protect the platform from undue load, and it routes requests to the appropriate upstream services. Factoring these high-level features into the edge service is a huge win for platform simplicity.
再利用問題そのものに戻ると、私たちは冗長を消除したいが、BFF 間の緊密な結合を招くことを望んでいません。したがって折衷的な態度があります:BFF 間の冗長を許容し、単一 BFF 内の冗長を消除。つまり一定レベルの BFF 間の冗長を許容します
もちろん、再利用の前提は複数の BFF の技術スタックが同じであり、その後冗長部分を識別してリファクタリングします。具体的には、共通部分を抽出する必要がある段階になった時、いくつかの選択肢があります:
-
共通ライブラリを抽出
-
独立した service として抽出
-
下流サービスに下沉
しかし共通ライブラリは通常結合の主要な源です。例えば下流サービスを呼び出す共通ロジックは BFF 間の結合を引き起こします。独立 service の方案は比較的優れており、新しい service をドメインモデルに概念化できます。同様に、共通ロジックを下流サービスに下沉させ、平級の下流サービスを依存関係のあるツリー構造に変えることもできます
どのように再利用問題を解決しても、再利用を行う必要がある時にのみ行うべきです。一般原則は:
Creating an abstraction when you're about to implement something for the 3rd time.
四.应用场景
モバイルデバイスと比較して、PC デバイスのパフォーマンスは十分に良いので、複数の下流サービスを直接呼び出せる(コストは高くない)ので、BFF を通さないのでしょうか?
実際には、フロントエンドアプリケーションに直接面向する下流サービスと比較して、BFF の意義は以下を実装するのに適していることです:
-
サーバー側テンプレート
-
データの集約(複数のインターフェース呼び出しを統合)、編成(フロントエンドが望む形式にフォーマット)、トリミング(フロントエンドが不要な情報を削除)
-
集約呼び出しの結果をキャッシュ
-
某 UI エクスペリエンス(モバイル端など)に特定機能を提供
-
第三者が使用する API。第三者の制限により追加されたロジックの維持を容易にする
BFF は下流サービスの上に位置する層であり、ユーザーエクスペリエンス粒度に細分化されているため、下流サービスよりも柔軟であり、特に第三者にカスタム API を提供するなどの差異化シナリオに適しています
五.業界実践
BFF の理念に従って、大きなバックエンドをフロントエンドエクスペリエンスに基づいて分割します。下図の通り:

具体的な実践では、BFF は通常図示の通りではなく、主な変化は:
-
ビジネスラインに基づいて BFF を分割
-
ゲートウェイ層を追加し、ルーティング、認証、監視、レート制限・サーキットブレーカー、セキュリティなどの機能を実装
ビジネスラインに基づいて分割された BFF は、下流基礎サービスの上に構築された業務型マイクロサービスのようです。ただこれらのマイクロサービスは対応する業務のフロントエンドチームが開発保守を担当します。広義には、より細粒度の BFF と理解できます。つまり各業務に対応する 1 つの BFF(もはやユーザーエクスペリエンスの差異に基づいて分割しない)
ゲートウェイ層は共通の境界サービスを実装し、認証、レート制限などを行い、BFF が業務関連の部分に集中できるようにします:
前端体験
--------------------
^ ^
| |
网关
------------
BFF BFF
----- -----
^ ^ ^ ^
/ \ / \
--------------------
下流サービス
さらに甚者は、ゲートウェイ層も分割して BFF と一対一に対応させます:
前端体験
--------------------
^ ^
| |
网关 网关
----- -----
BFF BFF
----- -----
^ ^ ^ ^
/ \ / \
--------------------
下流サービス
P.S.さらに、BFF を導入せず、転送サービスのみを追加してデータの集約、編成、トリミングなどの問題を解決するものもあります。GraphQL に類似していますが、無意味なデータ透過が発生しやすいため、通常は全カバーではありません(すべてのデータリクエストが転送サービスを通るわけではない):
前端体験
--------------------
^ ^
| |
転送サービス |
-------- |
^ ^ |
/ \ |
--------------------
下流サービス
探索
実践における BFF の探索方向は主に 3 つあります:
-
安定性:BFF の信頼性を保障。例えばログ、エラー分析、監視、アラートなどの手段を通じて
-
同構:BFF とフロントエンド体験に同じ技術スタックを使用。例えば Node ベースの同構方案
-
一体化:一方では下流サービス向けに mock 方案を提供し、他方では同構、非同構アプリケーションの共存を許可
BFF モードでは、フロントエンド開発者が一定レベルのフルスタック知識(サーバー側スキル、運用、セキュリティなどの知識)を掌握する必要があるため、自然に同構または一体化方案を通じて開発体験を向上させ、敷居を下げ、技術を感じなくさせたいと考えます
越来越多的開発者が、フロー、ビルド、環境、デプロイなど various 事に関心を持たなくて済むようになり、技術無感化(Techless)を実現し、すべての開発者が静かに楽しくコーディングできるようにすることを望みます。
六.利点
関心の分離
BFF モードの最大の利点は*関心の分離(separation of concerns)*です。下流サービスはビジネスドメインモデルに集中でき、フロントエンド UI はユーザーエクスペリエンスに集中できます:
バックエンドはビジネスドメインに集中でき、よりドメインモデルの視点から問題を考えることができます。ページ視点のデータはフロントエンド型フルスタックエンジニアに任せます。ドメインモデルとページデータは 2 つの思考モードであり、BFF を通じてうまくデカップリングでき、互いをより専門的かつ効率的にします。
分業の観点から見ると:
BFF モードは単なる技術アーキテクチャではなく、社会的分業の観点から言えば、BFF は多元的価値指向の分层アーキテクチャであり、各層には十分な空間があります。
自主権
チームの観点から見ると、従来の前後端分離の主な問題は:
-
サービスの拡張性と複雑さ
-
��後端チームの多対一関係。フロントエンドチームは必然的に細分化される必要があるため(技術実装の差異により、专人负责が必要)
-
クロスチームコラボレーションコスト。例えばフロントエンド UI 開発過程中、バックエンド API が変化する可能性がある(クロスチームの調整コミュニケーションコストが存在)
BFF モードでは、API の owner は対応するユーザーエクスペリエンスを実装するフロントエンドチームです。つまりフロントエンドチームが API の自主権を持つため、迅速に変更を調整できます
フロントエンドと BFF チームの一体化のもう 1 つの利点は、クライアント実装かサービス実装かを柔軟に選択できることです(例えば共通性の強いものはサービス実装、または迅速なリリース審査通過のためにサービス実装も可能)。クロスチーム調整は不要です
コメントはまだありません