摘要 Eclipse 設計的啟發:當代 SaaS 分散式架構的關鍵設計


整理關於 SaaS 架構設計的想法,部分是來自於 Eclipse 這個著名 Java IED 的設計概念。

大約從 2018 之後,VSCode 可以算是統一 Open Source 的 IDE 了,之前由 GitHub 開發的 Atom 在微軟收購了 GitHub 之後,已經將在 December 15, 2022 落下了句點,其他 Editors (還不到 IDE) 大多還是屬於輔助性質,像是 Notepad++ 。

而 VSCode 主要的設計者 Erich Gamma 則是著名的 Design Pattern 的共同作者之一 (又稱 GoF),而這個理論背後源自於他的實作,也是著名的 Java IDE - Eclipse,Erich Gamma 負責最核心的 JDT (Java development Tooling) 的設計。

2004 - 2012 年期間,我在 IBM 駐點開發 Rational 相關產品,其中主要就是 Eclipse Plugins 的開發,產品是給 Web Developer 用的工具,可以說就是在寫 IDE 的概念。過程曾經鑽研了 Eclipse Plugins、RCP (Rich Client Platform, XMind / DBeaver 就是這個開發的) / Equinox OSGi / SWT / JFace / EMF / GEF … 等設計概念,也因此對於 Eclipse 整個架構略有研究,而這些設計概念也不知不覺的用在之後工作上。

這些年的更迭與代換,我自己的工作環境 從 Windows 換到 macOS,開發工具從 Eclipse 換到了 Atom,然後又跳到 VSCode。在使用 VS Code 的過程,處處都聞到 Eclipse 的設計感。開始做分散式架構設計、重讀作業系統、學習 CS 基礎知識、探索 AWS / K8s … 等過程,發現這些背後的本質都有高度的雷同。


Eclipse 設計摘要

SDK / Platform

下圖是 Eclipse Platform 的架構圖:


圖檔出處:Platform architecture

Eclipse SDK 由一組完整的 Platform 元件組成,包含 Platform Runtime (OSGi)、Workspace、UI 元件 (SWT / Workbench / JFace)、文件 (Help)、協作 (Team) … 組成。基於這些基元延展的兩個重要應用則是 JDT (Java Development Tooling)PDE (Plug-in Developer Environment)。JDT 是給 Java 開發者用的整合開發環境,後者則是為了讓 Eclipse 具備延伸能力的開發環境。

Runtime: OSGi

Eclipse Platform 使用 OSGi (Open Service Gateway Initiative) 作為主要的 Runtime 標準。OSGi 是一個標準協議組織 (OSGi Alliance),也是一個標準服務平台 (Service Platform)。規範定義了應用程式生命週期與服務註冊、框架通訊、擴充機制 … 等等,如下圖所示。


圖檔出處:OSGi Framework Overview


圖檔出處:OSGi Framework Overview

Concurrency Infrastructure

整個 Eclipse Platform 同時有很多東西在前景跑 (Frontend),不管是 Views 還是 Editor,而這些前景的物件會相互傳遞訊息,傳遞的訊息需要被處理,這個處理背後的機制就是 Eclipse 提供的 Concurrency Infrastructure,用現代分散式架構來看就是個 Pub/Sub 架構概念。

整個架構背後透過 Jobs、IStatus、IJobManager、IJobChangeListener、IJobChangeEvent、IProgressMonitor … 等介面組成。

Extension Point

如圖中描述的概念,其中的 PDE 為了讓開發者可以依照 Platform 開發延伸應用程式,Platform 本身要提供一些介面做接點,這個界面稱為 Extension Point,而接入 Eclipse Platform 的動作稱為 Registry。從使用介面 (UI) 來看,有幾個主要的組成概念。


圖檔出處:Plugging into the workbench

Workbench Window / Page

最上層容器,裡面包涵視窗的 MenuBar / ToolBar、多個 Page,每個 Page 裡可以有一個 Editor Window + 多個 Viewer Window。Page 則是第二層的容器,主要是提供不同的 Perspective 用途。

Editor and View

Editor 是使用者輸入的主要 Window,通常是預設的 Focus 地方,使用者會在這裡做主要的輸入。實作上透過 Eclipse Platform 提供的 JFace 以及 EMF (Eclipse Modeling Framework) 處理,讓開發者可以自行開發符合各種語言特性需要的 Editor。

而 View 則是用來輔助呈現資訊的視窗,預設是檔案結構,在 Eclipse 裡稱為 Navigator View

  • Viewer 有多種呈現形式,舉例幾種:
    • Java Package View:基於 Navigator View ,但是以 Java Package 習慣的呈現方式。
    • Outline View: 根據 Editor 內容,反映出結構,像是 Java 的 Properties、Methods
    • Properties View: 用 Grid 方式呈現 Key / Value 的資料結構
  • Viewer 有個基礎抽象類別 (稱做 ViewPart),並且提供事件驅動介面,讓 Viewer 與 Editor 之間可以以主動、被動的方式連動訊息。
    • 實務上會用基礎類別實作不一樣的 Viewer,像是 Console、Debug 的 Runtime Variables。

預設的 Eclipse 有很多 View,如下圖看到的 Category 有 Git / Gradle / Help / Java … 等。

下圖則是 JDT 提供的 Debug 常見的幾個 Views:

預設的 Navigator View,其實就是檔案管理器,把實體檔案的結構具體地呈現出來,如下圖:

Project Explorer 是 Java 的 Viewer,會把 Package 的結構攤平,讓 Java 開發者更容易理解。

以此為概念,可以開發給不同 語言 (C#, Python) 或者 SQL … etc … 專用的 Viewers。

Perspective

中文翻譯成 視角觀點,是在 Workbeanch 裡的數個 Views + Editor 與 Layout (BorderLayout) 組成的設定。每個開發者,在不同開發階段,或者做不同任務時會有不同的角度需要。透過 Perspective 就可以把該階段的畫面設定儲存下來,也可以分享設定給其他開發者。

下圖是 Eclipse 預設提供的幾種 Perspective:

下圖的則是預設的 Java Perspective,可以看到上面四個 View、從左到右由大到小分別是 Project -> Packages -> Type -> Members,下面則是把偌大的空間留給 Editor。這是很多 Java Developer 最常用的了。

我有很長一段時間再分析一個龐大的 Code Structure,那個過程很常需要了解整個 Class 的繼承關係、抽象介面的實作、Java Projects 的依賴關係、Plugins 的依賴關係 … 等,這配置很常用。只要切到這個 View 就是要分析程式用的。

下面這個叫做 Rick's Perspective 則是我自己以前在寫程式時最常用的 Layout。

  • 左上除了 Project Explorer,還有 Type Hierarchy,分析程式碼結構用。
  • 左下方式 Debug 需要的 Expressions 與 Breakpoints / Runtime Variables
  • 右上角則是現在 Content 的 Outline
  • 下方 (South) 的上方區域,放的則是 Runtime 的控制 View,像是 Servers (Tomcat)、Debug (StepIn/Out/Over) 等 …
  • 最下方區域,則是 Console

這樣的配置其實是很個人習慣的,當年就靠這個配置寫了不少東西。


從 Eclipse 學到的分散式架構啟發

Eclipse 本身屬於 軟體層級 的架構 (Software Architecture),基於這樣的架構可以讓 Eclipse 達到擴充性。而我借用這個概念,把軟體架構變成 系統架構 (System Archtiecture) 層級的擴充架構,實作上就是基於 Web Service 為單位的擴充架構,也是現代基於 分散式架構 的 SaaS 產品要面對的核心問題:

  1. 通訊模式
  2. 擴充架構與生態系
  3. 多租戶架構與模型

1. 通訊模式:Concurrency Infrastructure

下面兩張圖是我很久以前在設計 Designing Test Architecture and Framework 時所寫的管理介面,大概類似於 AWS Console EC2 個概念。


畫面上可以看一般應用程式的 Menu、主畫面 (有 Tab)、每個資源的 Detail View (下圖右邊) … 等基本結構。

這是很常見的,但是上述三個東西 (Menu / Main Window / Detail View) 彼此之間經常是需要 資訊交換 的,像是 當點選 Menu 裡一個物件的時候,Main Window 與 Detail View 需要做連動,把資訊帶入,或執行對應的行為。我就利用類似 Eclipse 裡的 Concurrency Infrastructure 機制,讓彼此之間做通訊,後來我才知道這就是 Pub/Sub。

用 Google Slide 來說,下圖畫面中有三個區域:

  1. 上面的 Toolbar
  2. 左邊的預覽 Preview
  3. 右邊的編輯區域 (Editor)

截圖的 Focus 停留在左邊預覽的 第二頁,另外兩個區域的行為有:

  1. Toolbar: 對應的 MenuItem 因為選擇改變功能,截圖 格式 相關的功能都 Disable 了,因為與在 Focus 的地方無關。
  2. Editor: 顯示 Focus 對應的內容

這三個區塊彼此是怎麼勾通的?線性的思路,就是 Foucs 點下去之後,另外兩個直接 Listen 物件的事件,然後把對應資訊傳給另外兩者處理。這樣做沒啥問題,也可以動。但如果區塊有五個?十個?二十個?100 個?還是直接這樣 Listen Event?而且直接 Listen 代表著這整個行為是 Blocking 的,使用體驗也就不會好,通常也會因為 Blocking 而出現白畫面的現象。

而比較理想做法就是利用 Pub/Sub 這種非同步的方式,結構除了原本的三個區域,後面多了一個 Pub/Sub,而整個動作會變成這樣:

  1. 使用者點在左邊的 Preview
  2. Publish 一個 Message X,然後就返回。
  3. 另外兩個 (Toolbar / Editor) 去 Subscribe 對應的 Message
    • Toolbar 收到 Message X 處理定義的行為:Disable 相對應的 MenuItem
    • Editor 收到 Message X 處理定義的行為:顯示內容

這樣基本的概念就是:觸發 Event 以及處理 Message 兩者之間是非同步的,整個使用體驗可以做到完全 Non-Blocking 以及即時的效果。這個例子 1: 2 的,即使到了 1 : N 效果也不會有太多影響。

這概念類似於 Eclipse 每個 Extension 之間、或者 View 之間的溝通,這也是現代分散式架構常見的模型 Pub/Sub、在一個 Embedded 裡通常也會用 Queue 實作兩個 Device 的溝通、在作業系統則是透過 Inter Process Communication 實作 … 等。

通訊模式要解決的是:

  1. 狀態一致:像是交易、狀態機
  2. 資料交換:傳檔、匯入、匯出

通訊模式的關鍵技術則是:

  1. 狀態一致性問題Dapr 的設計與概念 有著不錯的實踐。
  2. 同步與非同步
  3. 相關關鍵基礎設施,參閱 服務治理

2. 分散式架構的擴充與延伸架構

生態系是很多企業發展到一定程度後,勢必會出現的概念,很多大型公司都有這樣的概念,像是:

  1. Devices: 基於設備上的應用程式、應用市集
  2. Extensions / Plguins / Add-on in Web Services
  3. Extensions / Plugins / Add-on in App
    • Line 在自己的 APP 裡搞的小程序
    • Chrome Web Store
    • VSCode Extensions
    • Eclipse Plugins

擴充 (Plugins)延伸 (Extension) 是兩個概念,前者是基於既有的系統的功能,垂直增加功能;後者則是基於既有的系統 水平擴充功能

  • 1) 是集中管理、端點發布的架構:也就是應用程式需要被 下載 到使用者端,進行安裝後能夠使用。
  • 2) 是集中管理、共同使用架構:也就是所謂的 SaaS,使用者不需要下載、安裝,直接透過 Browser 使用。
  • 3)2) 擴充,基於 2) 的結果繼續擴充。
    • OS 之於 Chrome 的 Extension 屬於這種。
    • iOS 之於 Line 的 小程序 屬於這種。

下圖是 Google Docs Slide 的 Plugin,稱為 Google Workspace Marketplace

水平擴充的例子在 Google 可以看到最好的例子,像是 Gmail / Google Docs / Slides / Spreadsheet / Calendar / Meet … 就是水平功能,屬於獨立的產品線(在組織上應當屬於獨立盈利單位, BU)。他們共享的則是 SSO 機制,以及背後共用的介面、認證授權、以及 Multi-Tenancy 的隔離機制(我把它稱為 Isolation Factor)。

分散式系統擴充架構 背後帶出的是另外一個 SaaS 平台的常見策略應用,也就是 Marketplace 或者稱為生態系,而背後的關鍵基礎建設則是:服務治理

擴充模式 帶來的好處是:

  1. 業務可拓展、探索性
    • 自己 (In-House) 開發
    • 外包 (Out-Source) 給其他公司開發
  2. 組織與架構的平衡性:參閱 看見怎樣的全貌 - 軟體開發的三體問題
  3. 開發可實驗性
    • 多種語言
    • 跨平台

擴充模式 的關鍵技術則是:

  1. 具備 通訊模式 所需要的基礎設施
  2. 具備 擴展性結構 的規格
  3. 具備 良好的開發、測試規範

擴充模式 在程式語言的各種實踐樣態:

  1. Function / Method …
  2. Java 的 import, C# 的 using
  3. Web Service
  4. RPC (remote procedure call), gRPC
  5. … 之後我會這個概念繼續掰下去 XD

3. 多租戶架構與模型

多租戶架構 (Multi-Tenancy) 是開發 SaaS 產品一定會面對的問題,其中 產品線 (前面 Google Docs / Slide ... 等例子)租戶 (Tenant) 的關係如下圖:

  • 綠色:產品,圖直接用 AWS EC2 / S3 / DDB 當例子
  • 藍色:使用者帳號,也就是 租戶概念 (Tenant)

多租戶架構設計的關鍵就是 隔離 (Isolation) 的實踐。

隔離 的概念,在各種應用系統都有,舉例來說:

  1. docker 實踐隔離的機制就是 cgroup, namespace, 隔離的是 CPU, Memory, Network, Storage 等計算機資源
  2. VM 實踐隔離的透過模擬硬體隔離資源, 隔離的是整台 PC Hardware
  3. K8s 透過 Namespace 隔離資源,隔離的是 deployment, pod, deamonset 這些 object.
  4. Relation Database 實踐隔離則有各種層級與模式, 參閱論文 The many faces of consistency
  5. AWS 的 VPC 透過 overlay 實踐 網路層級 的隔離
  6. 語言實踐隔離的方法:Class / Namespace 都是實踐的機制,隔離的是 物件的有效範圍
    • 如果不是 OOP (像是 bash),常用的隔離方法就是變數的命名加上 Prefix
  7. 程式語言 Runtime 記憶體與作業系統隔離的方式: 像是 Java JVM 在作業系統 User Space 要一塊記憶體,然後與一班應用程式隔離。
  8. WiFi Mesh 實踐的不是隔離,而是合併 ….

通常商業軟體談的隔離則是業務邏輯的隔離概念,通常是一種 Identity 的概念。主要是因為從資源層級的隔離切入,往往不是成本太高,不然就是工程浩大,說白點一開始根本不是這樣設計,改就是傷筋動骨。

所以大部分打帶跑的開發就是從 Identity 出發做隔離,實作上就是 User Session 的概念。而因為開發階段不一樣,每個產品線可能都會有自己的隔離名稱,例如早期 S3 使用的是 Canonical User ID 作為隔離的單位,後來才統一使用 Account Id 。我把這個隔離抽象稱為 隔離因子 (Isolation Factor),不同領域 Domain 會有不同名稱,做電商的會用 ShopId 做單位、開 Blog 的會用 UserId … etc。

多租戶架構與模型 帶來的好處是:

  1. 業務增長性
    • 與拓展不一樣
  2. 業績直接的成長

多租戶架構與模型 的關鍵技術則是:

  1. 隔離技術的實踐能力
  2. 隔離單位的定義:
    • docker 可以 in docker
    • k8s 可以 in docker
    • vm 也可以 in docker
    • 你知道 tenant 也可以 in tenant 嗎?…. 這種高 (ㄌㄞˊ) 級 (ㄌㄨㄢˋ) 的技術,一般鄉民是無法理解的。。。

SaaS 隔離具體的實踐是什麼?待我之後文章詳細整理與分析。


結論

聊聊分散式系統 一文提到這張圖:

這張圖已經包含了這整個概念與脈絡,背後想表達的就是 通訊模式擴充 概念,再加上這篇最後提到的多租戶與隔離的概念,一個基於分散式架構的 SaaS 平台基礎算式有了。

這篇起個頭,整理一些動手實踐、也翻滾幾年的想法,細節之後慢慢展開詳談。


延伸閱讀

站內文章

參考資料



Comments

2022/07/04 18:21:00





  • 全站索引
  • 關於這裏
  • 關於作者
  • 學習法則
  • 思考本質
  • 一些領悟
  • 分類哲學
  • ▲ TOP ▲