這次聚會我們先簡單的回顧一下上一次的討論,然後就切換到了下一個主題。基於前一次聚會高併發的討論,我們模擬一個簡單的架構然後開始演進。
建議方法中的陷阱
首先,我們有一個單體式的應用將 Web 伺服器跟資料庫都跑在同一台機器上。
+-----------------------+
|+---------------------+|
|| ||
|| Web Server ||
|| ||
|+---------------------+|
|+---------------------+|
|| ||
|| Database ||
|| ||
|+---------------------+|
+-----------------------+
當請求量增加之後,我們可能會先把 Web 伺服器和資料庫分離到獨立的機器中。
+---------------------+ +---------------------+
| | | |
| Web Server <----------> Database |
| | | |
+---------------------+ +---------------------+
當我們再次感覺到變慢的時候,我們可能會增加「快取伺服器」到我們的架構中。 像是增加一個快取伺服器到 Web 伺服器和資料庫之間。
+---------------------+ +---------------------+ +---------------------+
| | | | | |
| Web Server <------> Cache Server <------> Database |
| | | | | |
+---------------------+ +---------------------+ +---------------------+
當我們的快取伺服器故障時,我們的服務會再重啟之後恢復正常嗎?
實際上它可能不會在快取伺服器重啟後正常恢復,因為我們的快取伺服器遺失了所有資料同時 Web 伺服器依舊發出大量地請求到快取伺服器卻無法處理而轉送到資料庫上。
這就是所謂的「雪崩效應」,當一個服務發生故障時進而影響其他人變得不穩,最後造成整個服務停止。
我們的導師建議我們在我們的團隊成員了解快取伺服器的優缺點和整個框架或套件使用後會如何運作之前,不要輕易的去增加快取伺服器。
微服務能解決這一切嗎?
如果我們想要避免雪崩效應,你可能會聯想到這幾年很熱門的微服務(Microservice)
微服務是以「去中心化(Decentralize)」為目的設計的,這表示每個元件大多獨立運作而且很容易的重新部署。
但是這其實有點太過理想,我們的服務經常會有一些相依於其他服務的情況。像是 Web 伺服器就經常的依賴於資料庫。
這是另外一個關鍵我們需要在設計架構的時候去考慮的地方。
目前在微服務中最熱門的相依問題解決方式是製作一種叫做「邊車(Sidecar)」的服務來控制每個元件間的溝通,因為邊車通常會知道其他服務的存活情況以及是否可以被連接,因此能夠回報跟管理他目前所負責的服務。
我們的導師告訴我們架構大多是為了要解決某個問題才會被設計出來的。
另一方面,我們如果要在微服務中找到問題,我們必須知道在這連續的呼叫中是在哪個服務停止的。這也表示微服務的系統需要有一個強大的紀錄追蹤機制來追蹤系統中的每一個事件。
選擇某種架構付出的代價
在我們學習了一些最近熱門的關鍵字之後,我們開始討論是否適合使用微服務。
我們的導師告訴我們效能(Performance)涵蓋三個部分:
- 吞吐量(Throughput)
- 延遲(Latency)
- 記憶體使用(Memory Footprint)
他們會互相影響,這表示如果我們選擇了其中一個作為目標其他的項目就會變成代價支付出去。
在微服務系統中會將封包導向目標的服務,這也表示延遲會比其他架構還高得多。但是他的去中心化特性讓我們很容易的增加更多的元件來處理不斷增加的流量。
微服務是透過延遲來交換更大的吞吐量,讓我們擁有處理大量請求的能力。
也因此,如果我們的服務非常要求低延遲的話,微服務對我們的產品可能就不是一個好主意。
Domain-Driven Design
DDD 是我們討論的主題之一,我們的導師讓我們思考為什麼微服務變得熱門的同時 DDD 也同樣開始變得熱門。
實際上我們可以發現他們相似的在意「領域(Domain)」,他們嘗試將讓每個服務都專注在某一個業務上。這和我們平常使用的 MVC 是非常不同的,不過這也說明了為什麼 DDD 的設計會更適合微服務的需要。
另一方面,如果我們想要在公司中使用微服務。他通常取決於公司的規模或者在跨部門之前的溝通有些問題時,微服務可可能會是得不錯的選擇讓每個部門維護自己的服務。
不過我們也需要注意過度的設計在我們自己的部門中,因為我們很可能只需要一個單體式的應用在我們的部門或公司。另一方面微服務也有不少需求需要滿足,如果在一個部門中擁有過多的為服務可能會造成另外的問題。
資料的一致性
除了效能問題之外,資料在我們的架構中也是另一個重要的面向。每一個系統都會有他自己的狀態,而我們的服務則需要小心討論來決定使用強一致性或者最終一致性。
舉例來說,一個銀行系統必須是強一致性的。至少你不會預期銀行在你存入一些錢之後,顯示並沒有這筆紀錄。卻在幾小時完成一致性的檢查後,才顯示出來。
分散式系統其實也是一種資料一制的探討。
資料庫的演進
在一個系統中,資料庫通常是最直接跟資料一致性有關聯的主題。因此我們的導師讓我們先比較 RDBMS(關連式資料庫)、NoSQL 和 NewSQL 的差異。
RDBMS
在 RDBMS 之前還有一個叫做 Object-Orident Database (物件導向資料庫)的東西,雖然 PostgreSQL 有一部分的特性,但是我們並沒有繼續討論他。
基本上這是我們討論演進的第一個階段,令一方面因為他算是非常常見因此我們並沒有在這個時候討論太多。
NoSQL
在 NoSQL 的情況,我們透過將一致性作為代價來提高吞吐量。這也是為什麼 NoSQL 擁有很不錯的拓展性能讓我們非常簡單的去擴充。
不過 NoSQL 必須在應用層實作很多東西,因為 RDBMS 幫我們處理了不少事情,但是 NoSQL 並沒有。
另外一個特性是 NoSQL 是伴隨 SSD 的特性出現的,因此透過改變儲存資料的方式讓我們獲得高速的 Key-Value 資料存取能力。
NewSQL
NewSQL 比較類似於 NoSQL 的反思,人們開始使思考 NoSQL 作為一個資料庫還有所不足。實際上有很多東西不應該在應用層實現,而應該讓資料庫幫助我們來完成。
也因此開始開發 NewSQL 這種具備類似 RDBMS 的強一致性但是又有足夠的擴充能力的資料庫。
目前 NewSQL 還沒有變的熱門,而且也沒有太多開放原始碼的解決方案。
資料庫的選擇
在前面的討論,我們的導師讓我們分享選用一個資料庫的觀點和理由。
這裡有很多情況讓我們決定要選擇哪個資料庫:
- 資料庫的功能
- 使用的框架
- 團隊成員
- 客戶的偏好
實際上這沒有正確答案,就像前面在架構上的討論在不同的設計上會有不同的優缺點出現。
總結
實際上這篇文章還是缺少了很多細節,不過太多東西我實在沒辦法一次性的記住。
實際上在第一次聚會結束後我是有點擔心討論會止於一些計算或了解一些知識而已。
不過這次聚會我們的導師讓我們學到了一些新的方法跟觀點能夠直接應用在工作上。
最重要的是我們要在決定之前「找出計畫的缺點」並且重新檢視他,優點確實能給我們好處,但當系統發生問題的時候缺點才是我們需要面對的。
也因此,我們需要去決定一個架構是對我們的產品傷害最小的,也就是大多數的缺點跟我們產品的需求是不會有太多衝突。
如果對這篇文章有興趣,可以透過以下連結繼續閱讀這系列的其他文章。
- TGONext: 規劃高併發服務
- TGONext: 從缺點選擇架構
- TGONext: 資料庫變遷跟架構改變
- TGONext: 追蹤和技術債