摘要 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 的架構圖:
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)。規範定義了應用程式生命週期與服務註冊、框架通訊、擴充機制 … 等等,如下圖所示。
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. 通訊模式: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 來說,下圖畫面中有三個區域:
- 上面的 Toolbar
- 左邊的預覽 Preview
- 右邊的編輯區域 (Editor)
截圖的 Focus 停留在左邊預覽的 第二頁
,另外兩個區域的行為有:
- Toolbar: 對應的 MenuItem 因為選擇改變功能,截圖
格式
相關的功能都 Disable 了,因為與在 Focus 的地方無關。 - Editor: 顯示 Focus 對應的內容
這三個區塊彼此是怎麼勾通的?線性的思路,就是 Foucs 點下去之後,另外兩個直接 Listen 物件的事件,然後把對應資訊傳給另外兩者處理。這樣做沒啥問題,也可以動。但如果區塊有五個?十個?二十個?100 個?還是直接這樣 Listen Event?而且直接 Listen 代表著這整個行為是 Blocking 的,使用體驗也就不會好,通常也會因為 Blocking 而出現白畫面的現象。
而比較理想做法就是利用 Pub/Sub 這種非同步的方式,結構除了原本的三個區域,後面多了一個 Pub/Sub,而整個動作會變成這樣:
- 使用者點在左邊的 Preview
- Publish 一個 Message X,然後就返回。
- 另外兩個 (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
實作 … 等。
通訊模式要解決的是:
- 狀態一致:像是交易、狀態機
- 資料交換:傳檔、匯入、匯出
通訊模式的關鍵技術則是:
狀態一致性問題
,Dapr 的設計與概念 有著不錯的實踐。- 同步與非同步
- 相關關鍵基礎設施,參閱 服務治理
2. 分散式架構的擴充與延伸架構
生態系是很多企業發展到一定程度後,勢必會出現的概念,很多大型公司都有這樣的概念,像是:
- Devices: 基於設備上的應用程式、應用市集
- iPhone / macOS 的 App Store
- Android 的 Google Play
- Windows 上的 App Store
- QNAP App Center
- 其實 PS5 / Switch / XBox 上的下載遊戲也算。。。
- Extensions / Plguins / Add-on in Web Services
- Slack App
- AWS 的 Marketplace
- Shopify app store
- Facebook 應用程式
- 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 或者稱為生態系,而背後的關鍵基礎建設則是:服務治理
擴充模式
帶來的好處是:
- 業務可拓展、探索性
- 自己 (In-House) 開發
- 外包 (Out-Source) 給其他公司開發
- 組織與架構的平衡性:參閱 看見怎樣的全貌 - 軟體開發的三體問題
- 開發可實驗性
- 多種語言
- 跨平台
擴充模式
的關鍵技術則是:
- 具備
通訊模式
所需要的基礎設施 - 具備 擴展性結構 的規格
- 具備 良好的開發、測試規範
擴充模式
在程式語言的各種實踐樣態:
- Function / Method …
- Java 的 import, C# 的 using
- Web Service
- RPC (remote procedure call), gRPC
- … 之後我會這個概念繼續掰下去 XD
3. 多租戶架構與模型
多租戶架構 (Multi-Tenancy)
是開發 SaaS 產品一定會面對的問題,其中 產品線 (前面 Google Docs / Slide ... 等例子)
與 租戶 (Tenant)
的關係如下圖:
- 綠色:產品,圖直接用 AWS EC2 / S3 / DDB 當例子
- 藍色:使用者帳號,也就是
租戶概念 (Tenant)
多租戶架構設計的關鍵就是 隔離 (Isolation)
的實踐。
隔離
的概念,在各種應用系統都有,舉例來說:
- docker 實踐隔離的機制就是 cgroup, namespace, 隔離的是
CPU
,Memory
,Network
,Storage
等計算機資源 - VM 實踐隔離的透過模擬硬體隔離資源, 隔離的是整台 PC Hardware
- K8s 透過 Namespace 隔離資源,隔離的是 deployment, pod, deamonset 這些 object.
- Relation Database 實踐隔離則有各種層級與模式, 參閱論文 The many faces of consistency
- AWS 的 VPC 透過 overlay 實踐
網路層級
的隔離 - 語言實踐隔離的方法:Class / Namespace 都是實踐的機制,隔離的是
物件的有效範圍
- 如果不是 OOP (像是 bash),常用的隔離方法就是變數的命名加上 Prefix
- 程式語言 Runtime 記憶體與作業系統隔離的方式: 像是 Java JVM 在作業系統 User Space 要一塊記憶體,然後與一班應用程式隔離。
- WiFi Mesh 實踐的不是隔離,而是合併 ….
- …
通常商業軟體談的隔離則是業務邏輯的隔離概念,通常是一種 Identity 的概念。主要是因為從資源層級的隔離切入,往往不是成本太高,不然就是工程浩大,說白點一開始根本不是這樣設計,改就是傷筋動骨。
所以大部分打帶跑的開發就是從 Identity 出發做隔離,實作上就是 User Session 的概念。而因為開發階段不一樣,每個產品線可能都會有自己的隔離名稱,例如早期 S3 使用的是 Canonical User ID
作為隔離的單位,後來才統一使用 Account Id
。我把這個隔離抽象稱為 隔離因子 (Isolation Factor)
,不同領域 Domain 會有不同名稱,做電商的會用 ShopId 做單位、開 Blog 的會用 UserId … etc。
多租戶架構與模型
帶來的好處是:
- 業務增長性
- 與拓展不一樣
- 業績直接的成長
多租戶架構與模型
的關鍵技術則是:
- 隔離技術的實踐能力
- 隔離單位的定義:
- docker 可以 in docker
- k8s 可以 in docker
- vm 也可以 in docker
- 你知道 tenant 也可以 in tenant 嗎?…. 這種高 (ㄌㄞˊ) 級 (ㄌㄨㄢˋ) 的技術,一般鄉民是無法理解的。。。
SaaS 隔離具體的實踐是什麼?待我之後文章詳細整理與分析。
結論
聊聊分散式系統 一文提到這張圖:
這張圖已經包含了這整個概念與脈絡,背後想表達的就是 通訊模式
與 擴充
概念,再加上這篇最後提到的多租戶與隔離的概念,一個基於分散式架構的 SaaS 平台基礎算式有了。
這篇起個頭,整理一些動手實踐、也翻滾幾年的想法,細節之後慢慢展開詳談。
延伸閱讀
站內文章
- Study Notes - I/O Models
- 聊聊分散式架構的服務治理
- 聊聊分散式系統
- 摘要 Dapr 的設計與概念
- 看見怎樣的全貌 - 軟體開發的三體問題
- Designing Test Architecture and Framework
- Software QA 的職能條件
- Experience Dapr - Pub/Sub
- Install Mac OS Mavericks on PC (蘋果安裝筆記)