在研究某個軟體的系統架構,發現一個值得探討的問題。
當設計系統架構時,使用何種的視界去分析與設計,會得到不一樣的設計結果,但結果是否為當下最佳的解決方案?
局部視角
假設後端服務的開發團隊,收到開發 APIs 的任務,而且此 APIs 需公開於開放網路。
開發團隊以專業角度出發,基於資安考量的前提下,規劃每一支 API 的請求,都會進行 API 存取合法性的驗證。所以建立 Identity Server,負責 Token 的發送與驗送。
- 在每次呼叫 API 之前,都必須先取得一組 Token 資訊,這組 Token 資訊會包含著請求的有效時間限制以及使用者的資訊。
- 在呼叫 API 時,將取回的 Token 作為必要參數,一同送至 API。
- API 收到請求後,先進行 Token 的驗證。驗證失敗,直接中斷動作,反之,成功回傳 API 的資訊。

這種做法是很合理,因為 APIs 的本身暴露在公開的網路環境中,基於零信任的原則,所以必須對每組 API 的請求,都進行相關身份的驗證。
若思考的維度只關注在 APIs 的本身,很容易會陷入一種情境。當系統發現異常或整合問題時,APIs 端的開發人員會堅持 APIs 的設計沒有問題,一定是其他部份有問題,或是使用端有問題。
當前端與後端分別不同部門,在穀倉效率的影響下,這種事其實蠻容易發生的。因為大家都會站在自己的專業角度去進行設計,個別負責部份都很完美,但組合起來的時候就會發現一些很奇妙的問題。
全局視角
當思考的維度,從單純的 APIs 開發角度抽離,改為關注 APIs 所服務的對象、系統架構的全貌,客戶所關心的重點。
與相關人員確認後,會發現 APIs 主要提供站台使用,可以初步勾勒出的系統的全貌。

與站台的開發人員,確認會從 JavaScript 直接呼叫 APIs,進行業務層級的操作。

再進一步確認使用情境,發現首頁與特定頁面,需要使用 server side rendering(SSR) 產出頁面。以首頁為例,產出頁面過程中,需要呼叫 10 支 API 組成所需資料。

試著從分析 Client 站連入首頁時,系統一連串的動作行為,會發現在載入 server side rendering 的頁面時,所需要觸發的 API 背後的動作。
- 首先跟 Identity Server 取得一組 Token。
- 利用 Token,進行 API 的呼叫。
- APIs 收到請求後,會將 Token 傳到 Identity Server 進行驗證。
- 驗證成功後,進行 API 本身的職責,並回傳結果。
發現步驟 2~4 重覆 10 次,每個 API request 都會呼叫一次 Identity Server,進行 Token 的驗證。
總觀來看,其中 9 次的 Token 驗證其實是一個重複性的動作。當然不能說這一個設計有問題,可是從全面性的角度去審視系統架構整體,發現這樣的設計,會對 Identity Server 造成額外的負載,就需要評估這些負載的損耗是必要的嗎?或是可以節省下來?
當從局部的角度,去看待一件事情的時候,只有那一個範圍。當評估的維度,往上再拉一層,從全局的角度去看待這件事情的時候,其實會發現當初的最佳解,或許對整個系統而言可能是一個脆弱環節或是瓶頸。
實際的解法方向
既然發現了 10 次重複驗證 Token 的問題,從全局視角出發,我們可以怎麼解?
常見的做法是引入 API Gateway 來統一處理外部請求的授權驗證,讓後端的 microservices 信任 Gateway 轉發的請求;或是導入 BFF (Backend for Frontend) 設計模式,由一個專屬的 Backend 伺服器去跟後端要資料並聚合成一包,讓前端只需打一次 API 即可。
這類架構的補強,正是我們從「單一 API 視角」切換到「全局視角」後才能看見的權衡價值。
(註:想知道缺乏全局視角會造成什麼嚴重的系統慘劇嗎?可以看我的這篇除錯實戰紀實:API 流量異常暴增?抽絲剝繭找出現代軟體架構的隱形殺手)
小結
回歸到問題的本質,就是設計之初,是否有看見全貌,明白了解這個系統主要要解決的痛點是什麼?客戶要的是什麼?
其實在大多數的情況下,客戶根本不在意是用什麼樣的技術和方法,能不能解決問題、是否能滿足業務上的需求,這才是他們關注的重點。
局部最佳解,有時並非系統的最優解。
從局部最佳解來看的話,有時需要額外投入更多的資源進行開發。一旦回到全局的角度來看,有些設計其實是多餘的,或是對系統造成額外負擔。
一但發生未滿足客戶的要求,後續可能需要二次調整,這是一種過度設計造成的成本浪費。
倒不如在專案之初,所有成員提出方法後,進行系統全面性的審視,有時候就可以發現某些功能和設計其實是可以被忽略,或是發現有部分情境未被考慮,在未來可能是系統脆弱的環節。
延伸閱讀
- Andrew Wu, [架構師的修練] #2, SLO - 如何確保服務水準? 🔗
- Ruddy, 工程師的機會成本 🔗
💡 互動時間 軟體開發最難的往往不是寫 Code,而是避免陷入「穀倉效應」的局部優化。 你在團隊開發中,也曾遇過各部門堅持「局部最佳解」,反而導致系統整體效能崩盤的災難案例嗎?歡迎在下方留言,一起探討架構設計的取捨之道!
💬 留下你的想法
有問題、不同看法,或是你踩過類似的坑?歡迎留言討論,我會盡量回覆。