題幹與適用場景
一個 SaaS 平台要讓不同團隊交付檔案解析、規則計算和資料去識別外掛。外掛以 Rust、Go 或 C 撰寫,執行於多租戶服務;平台要求外掛不能任意讀取主機檔案或存取網路,介面升級不能令舊外掛全部失效,異常外掛可以停止並回滾。請設計基於 WebAssembly Component Model 的執行時,不綁定特定 Wasm 引擎。
本題聚焦元件邊界與能力治理,區別於「把任意 Wasm 當沙箱執行」。回答需要說明 WIT 如何表達介面、Canonical ABI 如何跨語言傳值,以及主機如何限制匯入能力。
面試官考察點
- 能否把 WIT interface、world、package 與元件匯入匯出映射到部署契約。
- 能否解釋 Canonical ABI 解決跨語言布局問題,但不自動解決權限、資源上限或業務相容。
- 能否設計最小能力、租戶隔離、取消、逾時、記憶體與 CPU 限制。
- 能否用版本化介面、轉接器、相容矩陣與可觀測回滾處理外掛生命週期。
普通回答只說「Wasm 比容器安全、啟動更快」。強回答會把介面、能力、資源、版本和證據拆成可測試邊界。
回答前需要澄清的問題
- 外掛是請求內同步呼叫,還是允許非同步工作、串流與長時間狀態?這決定逾時、取消與狀態保存。
- 外掛需要哪些主機能力?檔案、網路、金鑰與時間都應透過明確匯入取得。
- 介面相容要求是什麼?只保證新增可選欄位,還是需要同時執行多個 world 版本?
- 資源預算按請求、外掛版本還是租戶計算?沒有配額維度就無法證明隔離。
30 秒回答框架
「我先用 WIT 定義窄介面和 world,把外掛匯入能力與主機實作分開。元件遵循 Canonical ABI,因此不同語言的字串、列表和記錄可以按統一規則跨邊界傳遞,但 ABI 不等於授權。我在主機建立能力表,只向每次呼叫注入經租戶與版本校驗的檔案、網路或金鑰控制代碼,並設定 CPU、記憶體、呼叫深度、輸出大小和截止時間。執行時記錄元件摘要、介面版本、資源消耗與結果;新版本先在隔離租戶執行,通過相容矩陣與回放後再擴大,失敗時按版本路由回舊元件並保留稽核。」
分步驟深入解答
第一步:把業務契約寫成 WIT
為每項穩定能力定義小型 interface,例如 parser.parse、redactor.redact,再用 world 宣告元件提供及依賴什麼。輸入輸出使用明確記錄、列舉、錯誤與資源控制代碼,避免暴露主機內部物件位址或資料庫連線。
第二步:說明 Canonical ABI 的邊界
Component Model 為元件定義統一 Canonical ABI,使不同語言對字串、列表與複合型別採用可互操作的邊界表示。主機仍要處理線性記憶體複製、所有權、長度校驗與錯誤映射;「跨語言可呼叫」不代表「輸入可信」或「不會耗盡記憶體」。
第三步:把能力做成明確匯入
主機只實作允許的 WIT imports,例如 blob.read、clock.now 或 http.fetch,每個匯入都綁定租戶、資源 ID、方法、最大位元組數和稽核上下文。外掛取得的是短期控制代碼,不是資料庫憑據;主機在每次呼叫重新檢查狀態、配額與取消訊號。
第四步:設計隔離與資源預算
執行時為每次呼叫設定 CPU 指令或時間預算、最大線性記憶體、堆疊深度、並發數、輸出大小與遞迴呼叫限制。超限後取消元件工作並回收實例;非同步介面保存可觀測呼叫 ID 和取消狀態,避免主機執行緒永久等待。租戶預算與外掛版本預算分開記錄,防止一個租戶透過多個外掛繞過總量。
第五步:處理版本與組合
把 package、interface、world 與元件摘要作為發布身份。新增欄位優先使用可選介面或新 world;破壞性變更並行發布 @1 與 @2,由路由層按租戶和能力矩陣選擇。轉接器可轉換舊錯誤碼或欄位,但不能掩蓋語義變化。元件組合前校驗匯入、匯出、型別與資源所有權。
第六步:建立供應鏈與回滾
儲存元件摘要、建置來源、WIT package 版本、簽章、依賴與審核結果。載入前驗證摘要、簽章、允許匯入集合與漏洞策略。新版本先在測試租戶和回放流量執行,比較成功率、輸出差異、CPU、記憶體和尾延遲;異常時把路由權重切回舊摘要、停止新實例,並保留失敗輸入的去識別重播記錄。
高品質示範回答
「我會把外掛當成受版本和能力約束的元件。團隊先用 WIT 定義窄 interface 和 world,元件匯出業務函式,主機實作經授權的 imports。Canonical ABI 讓 Rust、Go、C 生成的元件共享字串、列表、記錄與錯誤的邊界表示,但主機仍需做長度、所有權和錯誤校驗。
每次呼叫建立帶租戶、外掛摘要與截止時間的 capability context,只暴露短期資源控制代碼;檔案讀取、網路存取和金鑰使用都經主機策略檢查並記錄稽核。執行時限制 CPU、記憶體、堆疊、輸出和並發,取消後銷毀實例。發布流程驗證元件簽章、WIT 版本、依賴和匯入白名單,先回放再分租戶放量。介面可相容就保留舊 world,破壞性變更並行執行新舊 world;指標或輸出差異超過門檻時按摘要路由回滾。」
常見錯誤
- 錯誤表現:把 Canonical ABI 當安全邊界 → 失敗原因:它只規定呼叫表示與轉換,不限制主機能力 → 修正方法:獨立設計 imports 白名單和每次呼叫授權。
- 錯誤表現:把資料庫連線或長期金鑰傳給外掛 → 失敗原因:洩露後無法按租戶和呼叫撤銷 → 修正方法:使用短期、最小權限的主機控制代碼。
- 錯誤表現:只限制模組記憶體,不限制輸出與並發 → 失敗原因:外掛仍可製造大回應或佔滿執行槽 → 修正方法:為呼叫和租戶設定完整資源預算。
- 錯誤表現:升級 WIT 後直接替換所有元件 → 失敗原因:舊 world 語義和錯誤處理可能不同 → 修正方法:並行版本、轉接器和相容矩陣先行。
追問及應對
追問一:元件需要串流處理大檔案怎麼辦?
在 WIT 定義受限的位元組串流或分塊讀取介面,規定最大區塊、背壓、取消和總位元組數。主機不把整個檔案一次複製到元件記憶體;控制代碼綁定租戶與物件權限,讀取結束或逾時立即關閉。
追問二:外掛要呼叫另一個外掛,如何防止能力擴散?
預設不允許任意元件發現其他元件。主機先驗證目標 world 和版本,再建立只包含必要介面的受限子呼叫上下文,把剩餘截止時間、租戶身份和累計預算向下傳遞。呼叫圖與深度納入稽核和限額。
追問三:如何證明升級沒有改變業務結果?
固定輸入樣本、邊界值、錯誤與取消場景,分別執行新舊元件並做結構化差異比較。對非確定輸出定義等價關係;線上先按租戶小流量採樣,比較成功率、欄位差異、延遲、資源和拒絕原因,達到門檻才擴大。