除了「加機器」,其實你的微服務還能這樣優化

語言: CN / TW / HK

生產實踐中,如果遇到業務流量變高導致服務負載升高甚至報警,我們的第一反應往往是「加機器」。


俗話說,能用錢解決的問題都不是問題。

俗話又說,充錢你就能變得更強。


但是,作為一個有理想有抱負的架構師,除了「加機器」,其實你的微服務還能更優雅、更精細地進行優化。


本文預計閱讀時間 10分鐘,將從以下三個方面展開:

  • 從「AKF擴充套件立方」說起

  • Y軸擴充套件的常用模式

  • z軸擴充套件的思想與應用

1、從「AKF擴充套件立方」說起

在上一篇文章,我們從「服務維度」學習架構師的常用能力——微服務設計與治理。

圍繞著微服務生命週期的七個階段,總結了常用的16條原則。

其中原則15在微服務服務治理實踐中非常重要,本文將重點進行拆解分析。

原則15:參考「AKF擴充套件立方」模型,服務除了「水平擴容」外,還可以考慮「功能拆分」或者 「資料分割槽」。


所謂AKF擴充套件立方體(AKF Scale Cube),是一個描述從單體應用到一個分散式可擴充套件架構的模型概念。

  • X軸:服務和資料的水平擴容。

  • Y軸:功能/業務拆分

  • Z軸:沿客戶邊界的服務和資料分割槽


「水平擴容」比較容易理解,就是我們常見的操作——加機器。

根據AKF模型,面對服務負載升高的情況,其實除了加機器外,我們還可以考慮「功能拆分」或者 「資料分割槽」。

2、Y軸擴充套件的常用模式

「Y軸擴充套件」相對複雜,我總結了幾種模式:

  • 微服務拆分。根據具體業務模型、領域模型拆分更細粒度的微服務。

  • 業務隔離拆分。利用訊息佇列,將線上業務(OLTP)和耗費大量資源的計算任務拆分隔離。

  • 核心與非核心隔離。對於一個微服務,可以將SKA客戶與普通客戶進行隔離,SKA客戶使用獨立的叢集資源,提高穩定性。

2.1 微服務拆分

某個微服務負載過高,一個非常常見的原因就是這個微服務承擔了過多的職責。這個時候,我們需要根據具體業務模型、領域模型拆分更細粒度的微服務。也是我們常說的「垂直拆分」。

最典型的拆分方法論就是按照領域驅動設計(DDD)進行拆分。

以電商領域為例,按照領域可以拆分為:

  • 使用者服務

  • 商品服務

  • 訂單服務

  • 評價服務

  • 其他

系統按照領域拆分為多個微服務後,各個微服務由單獨的團隊負責整個生命週期的維護,單獨部署執行。

這種隔離拆分的方式,能帶來以下優勢:

  • 提高整體系統的負載能力

  • 各個微服務間具備 獨立擴縮容、故障隔離 等能力。

2.2 耗時任務隔離拆分

「Y軸擴充套件」除了按照領域進行服務拆分之外,另外一種非常重要的拆分方式,是將線上業務(OLTP)型別服務中「耗時任務」進行隔離拆分。


我們服務一般會採用Tomcat或者Jetty部署,同時採用同步呼叫的方式。以Jetty為例,預設執行緒池最大執行緒數為200。如果請求中有耗時任務,影響了同步請求的RT,那麼執行緒池滿後就會阻塞請求。

正如利特爾法則(Little's law)表述的:
在一個穩定的系統(L)中,長期的平均顧客人數,等於長期的有效抵達率(λ),乘以顧客在這個系統中平均的等待時間(W);或者,我們可以用一個代數式來表達:


因此,耗時任務會顯著提高服務負載、降低線上業務服務的吞吐能力。

通過引入訊息佇列或者任務佇列框架,我們可以將耗時任務從線上業務服務中進行隔離拆分。

這種隔離拆分的方式,能帶來以下優勢:

  • 提高線上服務的吞吐能力

  • 避免耗時任務影響線上業務的穩定性。

2.3 核心與非核心隔離拆分

「Y軸擴充套件」的第三種方式,是將 核心 與 非核心 進行拆分。


比如,我們通常可能會將「核心介面」與「非核心」介面通過一個服務內的不同執行緒池實現隔離。但是在節點資源(cpu/記憶體/頻寬等)上並不能實現隔離。


因此,我們可以更進一步,通過叢集拆分的形式進行隔離。

通過服務路由的配置,將核心介面路由到核心叢集(一般節點配置更高),非核心介面路由到非核心叢集。

另外,也有saas服務,通常會對SKA客戶做獨立叢集,也是類似的邏輯。

其實按使用者拆分隔離跟「資料分割槽」有一點類似,也可以歸類到「z軸擴充套件」

這種隔離拆分的方式,能帶來以下優勢:

  • 精細化提高服務吞吐能力(針對核心介面、核心客戶)

  • 核心業務獨享資源,提高核心業務穩定性

  • 避免非核心介面/使用者 影響 核心介面/使用者 的穩定性

3、Z軸擴充套件的思想與應用

Z軸擴充套件的核心思想,是基於請求者或使用者獨特的需求,進行系統劃分,並使得劃分出來的子系統是相互隔離但又是完整的。

生產實踐中,常用的z軸擴充套件有兩種應用:

  • 單元化架構

  • 資料分割槽

3.1 單元化架構

單元化架構主要關注的是應用部署、呼叫層面的問題。

一個單元,是一個五臟俱全的縮小版全站,它部署了所有微服務。

但它又不是真正的全站,因為每個單元只能操作一部分資料。


從這裡我們也能看出,單元化架構要求系統必須具備的一項能力——資料分割槽。

當然,僅把資料分割槽了還不夠,單元化的另外一個必要條件是,全站所有業務資料分割槽所用的拆分維度和拆分規則都必須一樣。


一般來說,我們絕大多數系統都是面向使用者的,按使用者維度對資料分割槽,是一個最佳實踐。

當然,如果是全球化部署的單元化架構,還需要考慮按照地域進行分割槽。

3.2 資料分割槽

資料分割槽(shard),即是將全域性資料按照某一個維度水平劃分開來,每個分割槽的資料內容互不重疊,這也就是資料庫「水平拆分」所做的事情。


前面提到了「資料分割槽」是「單元化」的必要條件,但是「資料分割槽」還有其他很多場景應用。


最典型的,就是MySQL單機瓶頸後,需要進行「分庫分表」。在服務中需要引入一些支援資料拆分和路由的中介軟體,如sharding-jdbc、mycat等,在資料層面需要配置相應的分片邏輯。


另外,其他資料庫的分割槽擴充套件(如redis叢集、mongo叢集等),也是非常典型的應用場景。

一般包括以下幾種資料劃分的方式:

  • 資料型別(如:業務型別)

  • 資料範圍(如:時間段,使用者 ID)

  • 資料熱度(如:使用者活躍度,商品熱度)

  • 按讀寫分(如:商品描述,商品庫存)

4、小結

本文從「AKF擴充套件立方」說起,介紹了提高服務負載能力的幾種服務治理方式。

除了X軸擴充套件(加機器)外,還可以通過Y軸擴充套件(功能/業務拆分)、Z軸擴充套件(資料分割槽)等方式,更優雅、更精細地進行優化。


希望能夠拋磚引玉,提供一些啟發和思考。如果你有其他補充和建議,歡迎留言討論。




往期熱門筆記合集推薦:


原創:阿丸筆記(微信公眾號:aone_note),歡迎 分享,轉載請保留出處。

沒有留言功能的悲傷,掃描下方二維碼「加我」聊些有的沒的吧~

                                                                              覺得不錯,就點個  再看 吧👇



本文分享自微信公眾號 - 阿丸筆記(aone_note)。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。