後端有 Microservices,那前端呢?初探 Micro Frontends 的世界

文/Andy Chen

前言

最近筆者在工作上一直聽到後端工程師們在談論 Microservices 的架構設計,聽到的當下立馬去查詢才知道原來 Microservices 這麼潮,身為前端工程師的我當然也希望前端也可以有這麼新穎的架構,於是這篇文章就要來跟讀者介紹 Micro Frontends

什麼是 Microservices?

在開始進入本篇文章主題之前要先跟讀者們介紹什麼是 Microservices

Microservices 是一種軟體架構,專注開發在每一個小型功能或者服務上,最後再利用模組化的方式組合出一個大型的應用程式。

如果讀者是前端工程師的話可能會覺得上面的敘述很像是 ES6 module 的架構,開發者只需要專注在每個 module 上的開發,最後再利用 Bundler 打包這些 module 形成一個完整的頁面甚至是應用程式,像下圖這樣。

Webpack module bundler

不過後端跟前端完全不一樣,後端是藉由一個又一個的 request 來 real time 的執行相關的程式碼,所以在 Microservices 的架構中,想要讓一個又一個的服務能互相溝通,這時候就是要仰賴各個 API 了。

Simple Microservices Structure

但這時候會有一個很大的問題,假如這三個 Service 對於前端來講有高度相依性,以上圖為例:今天一個完整的購物網站必須要先讓使用者登入後才可以進行購買商品以及去購物車結帳,這時候在 Client 端就必須要分別打三次 API 並且互相等待才可以完成這整個流程,甚至假如剛好不小心有一個 Service 壞了需要重新啟動,這時候可能會先產生一個過渡期的 API 避免 Client 端打到有問題的 Service,可是 Client 端也不可能每次都會去記住這個新產生的 API,所以這勢必會造成一個很大問題。

這時候其實可以在這些 Services 上添加一個 API Gateway,對於 Client 端來說我只需要對到一個 Gateway 就好,對於這個 Gateway 來說我一樣是去呼叫各個 Service 並且把資料都處理完後再回傳給前端。

Microservices with API Gateway Structure

如果有讀者本身是 SRE 熟悉 Docker 或者 K8s 這種用來自動部屬容器化應用程式的平台,對於上面這張圖應該更熟悉了!像 K8s 就有類似 API Gateway 的 Ingress 而 Docker 則有 routing mesh

不過光有 API Gateway 其實還沒辦法凸顯 Microservices 的特色,在 Microservices 的架構中其實每個 Service 都可以有自己的 DB,目的就是為了不要讓每個 Service 之間會互相關聯。

Final Microservice structure

但這樣做其實有幾個缺點:

  • 很難保證資料的一致性

以上圖為例,假如今天有一個 member 被註銷帳號,但這個 member 在被註銷帳號之前在 shopping cart 這個 Service 中有待結帳商品,這時候就會出現 member 資料不一致的問題。

  • DB 資料遺失

當某一個 Service 壞了需要重啟,這時候 DB 的資料有可能就會遺失導致後續的資料出現錯誤。

為了改善這些缺點這時候就可以將這些 Service 的 DB 設計成可棄性,換句話說就是這些 DB 只是用來作為短期的資料存取而已,背後還有一個共用的大資料庫去更新這些資料,通常都會利用 Redis 這種 cache DB 來進行設計。

為什麼需要 Microservices?

Microservices 的好處就是可以專注開發在每個小服務上,舉例來說以一個購票網站可能會在短時間內湧入大量的流量,這時候 race condition 就顯得相當重要,這時候就可以利用 Go 語言進行開發,亦或者是要開發一個以效能為主的服務,這時候就可以用 Rust 進行開發。

上面也提到 Microservices 必須要仰賴 API 之間的溝通,所以通常在企業等級的產品上都會有拆分模組販售的需求,假如這時候就是利用 Microservices 架構進行開發的話就很好拆分每個服務了。

使用 Microservices 架構的企業以及平台。來源:維基百科

這些都是使用 Microservices 後所能帶來的好處,所以假如讀者今天需要開發一個非常複查且龐大的平台,這時候不妨可以利用 Microservices 的架構進行開發喔!

Monolithic Architecture(單體式架構)

講完了 Microservices 後相信讀者應該對於這種架構有了初步的認識,與 Microservices 不一樣的架構就是 Monolithic Architecture(單體式架構)。

一般來說我們正常開發都是使用 Monolithic Architecture,在 Monolithic Architecture 的架構中都會把平台中所有內容都包裝起來,像下圖這樣:

Monolithic Architecture

這種架構不是不好,但假如今天想要拆分或者擴充平台上的 Service 其實都會比較麻煩一些,而且也會怕牽一髮而動全身,甚至所有的 Service 背後都會連到同一個 DB,這樣極有可能會讓 DB connection 同時連線過高導致 request 一直發送失敗,所以這也是 Microservices 想要解決的其中一個痛點。

什麼是 Micro Frontends?

Micro Frontends 可以想像成前端版的 Microservices,在後端的世界中強調一個又一個 Service 而在前端的世界中則是強調一個又一個的 modules,如何將網頁中每一個 module 有效的拆分就是 Micro Frontends 要做的工作。

Micro Frontends 的實現方式

接下來要跟讀者介紹的是 Micro Frontends 的實現方式,其實 Micro Frontends 有蠻多種實現方式的:

  • iframe

透過 iframe 的特性讓每個被載入的區塊頁面都可以獨立運行,假如需要有資料上的溝通也可以利用 window.postMessage 來完成,但這樣做會有非常多的缺點,像是有可能載入同樣的程式碼、UI 難以控制、甚至可能會有潛在的資安風險,所以筆者還是建議讀者不要用此方式來進行 Micro Frontends 的實現方式。

  • Client side 利用 JavaScript 載入 module

這個方法簡單又粗暴,就是利用 JavaScript create 出 script tag 後,接著再用 script tag 去載入相關的 module,最後再將其內容塞進去對應的 div 內,但缺點就是無法使用 SSR,整體寫法會像下圖這樣。

client side load modules by javascript
  • Web Components

Web Components 可以說是最多人拿來討論的 Micro Frontends 的實現方式了,雖然我們在現今的網頁架構中可以自由地 import 大神們寫好的套件,但難免都會遇到以下幾個問題:

  1. 套件相依性的問題:需要安裝只有該套件才會使用的 library,這會造成整個 node_modules 相當龐大。
  2. Scope 問題:前端為了樣式上的變化通常都會有藉由許多的 className 來進行樣式上的改動,但有可能因為該套件也有撰寫一樣的 className 導致很多時候都需要各種 override,長期下來也會是一種專案維護上的負擔。
  3. 版本相容性問題:只要框架進行大改版,基本上就很容易出現套件無法兼容新版本的狀況,這時候只能等套件作者升級版本之後才能再次使用,相信這個狀況也是許多開發者都會面臨到的困境。

瀏覽 1,700 次

覺得不錯的話就分享出去吧!
1 2下一頁

發佈留言

Back to top button