iT邦幫忙

2022 iThome 鐵人賽

DAY 5
2
Software Development

軟體架構師的自我修養系列 第 5

[Day 5] 微服務架構的八大謬誤

  • 分享至 

  • xImage
  •  

微服務架構是近幾年很流行的主題,過去有非常多研討會在談論如何部署、管理和實作微服務,但最近這個趨勢減緩了。取而代之的是,大家都開始討論微服務的複雜度。肇因於微服務的高複雜度,人們已經不把微服務當成仙丹妙藥,而僅是當作一個可行方案來對待。

什麼是理想的微服務?

但在開始介紹微服務前,讓我們先來看看理想的微服務應該長什麼樣子。

理想上的微服務應該具備以下這些特性:

  • 沒有共用的程式碼
  • 沒有共用的資料
  • 在特定領域上有獨立的上下文邊界
  • 能夠個別部署
  • 單一職責原則

用架構圖來描繪大概會是這個樣子。

當客戶端與後端系統溝通時,後端通常透過API閘道器根據某個規則將請求路由到特定為服務上,而該微服務可以獨力處理請求而不需要透過別人參與。

那現實世界又是什麼樣子?

現實世界往往不像我們想像的這麼美好。

http://www.alibati.com/horse

你知道這是什麼動物嗎?

據我所知,至少有三種可能,可能是馬,也可能是驢,甚至是騾。

為什麼畫成這樣?

一開始我們都嘗試根據理想或教科書上的架構描繪出來,這時一切看起來都很完美。但隨著時間流逝,越來越多需求被加入,我們能使用的時間被壓縮,甚至我們還必須解決已經發生的錯誤。

最終,這匹像馬的動物會越來越潦草。

如果一開始至少有個好的設計和計畫,我們還可以從形狀判斷這可能曾經是一匹馬。若是一開始根本沒設計,那連他最後長什麼樣,我們都無法想像。

用架構圖來表示就會像下面這樣。歡迎來到現實世界。

A、B和C都有自己的職責來處理領域邊界內的任務,但隨著需求成長,A發現需要B的資料,B需要C的功能,甚至C要回頭來呼叫A。最終,架構變成一個大泥球(big ball of mud)。

有許多原因:

  1. 通常,一個組織沒有安排架構師這個角色。所以沒有辦法正確根據需求演化系統。
  2. 正因為沒有架構師,系統無法在最初就被正確且清楚定義。
  3. 專注在將功能快速交付而忽略了非功能性需求(non-functional requirements)。
  4. 回饋週期很短。我們必須在短時間內就要能夠回應任何線上問題。
  5. 所有的事情都是發生在線上,不允許功能關閉,直到商務需求消滅。

在了解了軟體開發的現實面,接下來讓我們來看看設計微服務我們會碰到問題。首先要了解,微服務系統本質上就是高度分散的分散式架構,因此在分散式架構上碰到的謬誤同樣也會出現在微服務上。

分散式系統的八大謬誤

網路是可靠的

人們總是假設兩個端點間的網路是穩定可靠的。但事實是,在網路上的封包有可能遺失,甚至連線有可能中斷。

因此,分散式系統必須要有重試的機制才能盡可能提升可靠度。

網路沒有延遲

在設計分散式架構時,常常有一個潛意識的認知是兩個端點間沒有延遲,造成設計時將一些功能分散到多個端點上執行。

不幸的是,端點間的延遲永遠不可能是零,就算是內部網路也一樣。

因此在做遠端呼叫時,設定一個超時閥值是很重要的,即使資料庫連線也是。此外,短時間頻繁的呼叫也應該盡量包裝成單次,以Redis為例,要善用pipelinemulti來減少端點間的來回次數(RTT)。

頻寬是無限的

人們總是感覺端點間的網路頻寬沒有限制,所以肆無忌憚的傳送資料。

事實上,端點間的頻寬小到超出你的想像。

特別是一些資料庫的查詢,例如MySQL的SELECT *,往往會把頻寬耗盡而不自知。當需求成長,資料表也會隨之變大,可能有許多大型的資料例如BLOBTEXT會被寫入表中。此時,原有沒問題的SELECT *會超乎你想像的耗用頻寬。

網路是安全的

這是常見的陷阱,事實上人們總是認為內網很安全。

但其實一點也不,這也就是為什麼「零信任(zero trust)」這幾年被廣為提倡的原因。

拓墣不會改變

這個謬誤很有趣。人們覺得網路拓墣不會改變,所以兩個端點始終能夠透過預定義的IP或FQDN找到對方。

但現實是,拓墣會因為很多不同的原因改變,包含VPC分割、公有雲遷移或者系統演化等。

有一個系統管理者

我們總是期待會有至少一個系統管理者來管理服務。

通常在每個組織中,都會有一個維運的角色來維護系統。因此,維運部門扮演系統管理著的角色,一但有任何問題發生,維運部門都可以第一個發現。

大錯特錯。

任何系統都必須具備可觀測性(observability)且系統開發者必須要有能力從遙測中找出潛在的問題。

有四種常見的遙測指標:

  1. Logging:系統執行時留下的執行紀錄,用以追蹤系統行為,且在分散式系統中,必須要有能力追蹤跨系統的行為。
  2. Tracing:用來追蹤任務的執行週期,例如完成任務的總耗時等。在分散式系統中常用的工具有jaeger或open-tracing等工具。
  3. Metrics:在系統執行時可以度量的狀態,例如API的執行次數、錯誤次數等。
  4. Profiling:系統的背景資源消耗,例如CPU和記憶體等。

沒有傳輸成本

這其實是很嚴重的謬誤。

我們必須了解任何遠端呼叫都有成本,特別是在公有雲上,這成本更加可觀。即使只是存取資料庫或對外呼叫HTTP請求,這些行為都有成本。

所以不管是什麼遠端呼叫,都要優化,無論是呼叫次數或者資料大小。

網路是同質性的

這是很容易忽略的陷阱。

網路絕對是異質性的,所以當一個端點呼叫另外一個端點,我們無法保證這些呼叫的順序跟預期相同。換句話說,不能對遠端呼叫的順序有錯誤的期待。

結論

經過這些討論,我相信我們都同意分散式架構真的很複雜。

微服務是由無數端點組成的大型分散式架構,每個端點的設計都必須考量剛提到的各種因素,更有甚者,微服務也有自己要面對的議題,例如資料一致性、系統擴充性等諸如此類。

因此下一篇文章我們會來聊聊微服務的專屬議題。


上一篇
[Day 4] 介紹分散式交易
下一篇
[Day 6] 微服務架構的九大挑戰
系列文
軟體架構師的自我修養31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言