延續上一篇的系統設計,我們基本上在雲端架構方面,建議與 DDIA(Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems (Paperback),非常建議架構及資料庫工程師閱讀)書中提到的維持高穩定性,高擴展性,高維護設計出產品的架構,
圖片來源:Microsoft 全球網路圖
在大量使用Azure的微服務下,雖然我們可以說 Azure 雲端服務商這麼大應該不會有問題吧?
天有不測風雲,多積陰德不比做好預防措施實在。
但實際上,就算是 Azure, AWS, GCP 等雲端服務商,偶爾也會發生區域性的災難性失效問題,像是海底電纜斷掉、CloudFlare的Regex寫錯及各服務區域故障等問題,我們必須要考量的是:
Azure 區域間延遲統計資料 圖片來源:Azure
選好了區域之後不代表雲端服務商在該區域會建立服務中心,可能需要跨區連線,因此對於該區域跟最近的可用資料中心的連線品質與速度是我們考量的範圍之一。
至於為什麼要特別針對網路速度來著重說明呢?因為我們在 Serverless 的情況下大量把功能拆分到各項不同的雲端服務來處理,而這些雲端服務實際上都在不同的設備上,這些設備之間有連線上的延遲問題,而這些服務所用的設備有可能在某些地區沒有提供,而造成必須要跨區連線使用服務的問題,而在設計上考量這些延遲並最大化縮短各項服務間的來回延遲也是我們之間的開發重點之一。
而在電商的系統設計上,前端託管的Web App較沒有建議的放置區域,因為前端在設計託管上,會採用CDN(Content delivery network)的方式讓使用者根據地理位置去拉取靜態網站檔案,而Azure Api-management之後的後端資源的擺放位置就會很推薦放在產品主要服務地區的區域中心。
前段所提的都是雲端服務的區域擺放位置,充分了解選用雲端服務的限制及能耐也是穩定性的測量標準之一,限制在官方文件上會提到一部分,剩下的限制卻可能會出現在Stack Overflow,雖然在Serverless的概念上是無限多負載的概念,實際上雲端服務商也是有一個主機在處理這些隨選隨用的資源,變成有點像是共用主機的概念。
Azure Api-management 定價 圖片來源:Azure
既然是有主機,只是變成共用的,那就代表還是有某種上限,實際上筆者在某些大型電商專案產品上有實驗過壓力測試的概念,在非常高量(基本上一般產品不太可能達到的可能是百萬次等級水準)同步併發的瞬間,標榜無上限的Api轉發服務還是會有長達一兩秒的擴展時間,但由於 Serverless 的概念是預設好自動縮放機制,大多情況這樣高量的負載對於雲端服務上都還是游刃有餘,由於壓力測試服務費用比較昂貴,筆者就沒有在Azure的各項服務上做一些性能測試指標來檢測看看共用 Serverless 的主機會是使用什麼等級的主機當共用資源。
往往是帳單比那些價格表誠實很多。
而在電商的API取捨上,基本上一個Api Management的便能夠應付很多部分,在MVP架構下,通常用不太到太特殊的部分,但有些功能可能會使用到Websocket,在Azure目前的服務中,目前還只能使用Azure Application Gateway託管的服務來轉發Websocket,而其他雲服務商已經在Api管理層面處理好可以選用Websocket類型的服務。不太了解未來會不會整合,但這也是各雲架構在實作上因為服務的支援性不同而必須做出考量的部分。
上帝為你關上一扇門,是你自己要找到洞鑽出去!
Azure Functions
接下來要寫 Functions ,實作部分我留到後面實戰部分來說,基本上Serverless的概念就是,一個邏輯就是一個Functions,不要全部集中處理,會使用到高資源運算或是長時間需求的,使用Functions的費用可能會比開一台簡單的Server運算來的高昂。
先講幾個實作上應該要有的檢查清單:
在Serverless的概念上,通常傳到Azure Functions的時候,通常已經概略知道資料傳進來的格式,除非是前端或是呼叫的單位亂寫亂傳被駭,不然資料進來的時候格式不太會有例外狀態,這時候做好資料檢查很重要,畢竟Azure Functions有可能會因為程式出錯的狀況導致停擺,好一點的只是停擺5分鐘Timeout,壞一點的可能卡死60分鐘,加上佔用一個Connection在資料庫。
勤勞一點針對每一個Functions預想好各種可能突發狀況,設計好最長的停機時間。筆者團隊的產品在其他雲服務商有6百多隻Functions,對於管理這些Functions初期有非常多的問題,但設定好IaC概念,利用版本控制來自動化部署,會節省不少時間,在撰寫程式碼的時候,也必須要考量到共用程式碼的部分,程式碼中如果有共用自己寫的驗證機制,額外做一個Function來驗證,並在需要驗證的時候傳呼,會比較好維護。
而在電商的接收訂單方面,最好是採用寫入資料庫即關閉,並在關閉前觸發另一個Functions來做其他動作,一方面是因為消費者在訂單建立的期間如果覺得等待時間過長,很可能就因為沒耐心就導致掉單的狀況。另一方面有些人設計商品會在訂單建立當下就扣庫存而非金流成立就扣庫存,所以在搶購的事件下,如果因為訂單成立時間過久加上Timeout,消費者可能會對於品牌極大的失去信心。
沒有最好的架構,只有最適合產品的架構。
Azure SQL Database
資料庫對於所有人來說應該是最想不到怎麼樣 Serverless 的概念了。在Serverless的概念下,整個資料庫基本上可以當作一個資料中心,也就是說整個資料中心就是你的Database,在實際意義上資料碎片會跟別人放同一個地方,但讀取上是完全分離的,而處理這整個資料中心的運算,都是由分配的計算核心來處理寫入跟讀取,而連線的數量選用vCore的話基本上都是30,000,如何運用彈性縮放的方式處理SQL資源也是重點之一。基本上在Azure Functions處理好連線問題,透過平衡負載來平均分配連線數到SQL資源池,應該可以處理大多需求,真正要討論資料庫的設計不是此篇重點。可能在高負載的情況下需要做到寫讀分離,但在各個雲端服務商的資料庫結構其實不太一樣,資料庫的自動擴展可以在Azure api-management那層處理到預警的部分,使用預警的方式來提早做到縮放資料庫,可以避免某些情況下的尖峰負載導致資料庫滿載的問題。
在設計電商基本架構上,應該充分了解每一個採用的服務的性能跟限制。就好像用一個長短不一的木板建構的水桶,會有一個明顯的短板效應,平常負載量低的時候,也許都不會覺得網站的穩定性對品牌經營有什麼影響,一但開始了各種行銷活動,流量漸漸擴大的時候,這時候系統的能耐漸漸的會被檢測出來。這兩天講了非常非常基本的電商架構概念,也因為這系列文章主要是探討 Serverless 架構面的系統設計,筆者在職的公司產品中有Serverless的平台架構,也有非常多人使用的Woocommerce平台,而Woocommerce平台雖然在各個系統方面趨於成熟,但最大的問題是他非常多功能是需要動態網頁(Dynamic Site)來驅動的,像是外掛插件、購物車等等。導致在高負載的情況下仍然需要使用容器擴展的方式平衡負載,而在其中如何做到轉換成全Serverless核心是一門高深的學問,目前筆者團隊已經將部分轉為Serverless(某些國外團隊也在努力這件事情),但在外掛模組方面轉換的話,就必須要每一個外掛模組做一個手動切換,可能的方式會是取代整個Wordpress的內建函數,直接整個Wordpress變成一個IaC建構的系統。
明天預計會帶大家看看如何利用Serverless來擴展像是自動化客服(聊天機器人語意分析)、視覺分析等雲端服務,並接入上面電商MVP架構,以達到高可擴展性的需求。