當前位置:
首頁 > 科技 > 如何避開陷阱,設計一個成功的微服務架構?

如何避開陷阱,設計一個成功的微服務架構?

微服務是近幾年非常火熱的架構設計理念,我們需要正確理解微服務,否則如果只是跟風拿來就用,既不會用,也用不好,用了不但沒有效果,反而還可能有副作用。

今天我們就來深入理解微服務,如何避開陷阱,設計一個成功的微服務架構。

微服務的陷阱

1. 服務劃分過細,服務間關係複雜

服務劃分過細,單個服務的複雜度確實下降了,但整個系統的複雜度卻上升了,因為微服務將系統內的複雜度轉移為系統間的複雜度了。從理論的角度來計算,n 個服務的複雜度是 n×(n-1)/2,整體系統的複雜度是隨著微服務數量的增加呈指數級增加的。下圖形象了說明了整體複雜度:

粗粒度劃分服務時,系統被劃分為 3 個服務,雖然單個服務較大,但服務間的關係很簡單;細粒度劃分服務時,雖然單個服務小了一些,但服務間的關係卻複雜了很多。

2. 服務數量太多,團隊效率急劇下降

微服務的「微」字,本身就是一個陷阱,很多團隊看到「微」字後,就想到必須將服務拆分得很細,有的團隊人員規模是 5~6 個人,然而卻拆分出 30 多個微服務,平均每個人要維護 5 個以上的微服務。

3. 調用鏈太長,性能下降

由於微服務之間都是通過 HTTP 或者 RPC 調用的,每次調用必須經過網路。一般線上的業務介面之間的調用,平均響應時間大約為 50 毫秒,如果用戶的一起請求需要經過 6 次微服務調用,則性能消耗就是 300 毫秒,這在很多高性能業務場景下是難以滿足需求的。

4. 調用鏈太長,問題定位困難

系統拆分為微服務後,一次用戶請求需要多個微服務協同處理,任意微服務的故障都將導致整個業務失敗。然而由於微服務數量較多,且故障存在擴散現象,快速定位到底是哪個微服務故障是一件複雜的事情。

5. 沒有自動化支撐,無法快速交付

如果沒有相應的自動化系統進行支撐,都是靠人工去操作,那麼微服務不但達不到快速交付的目的,甚至還不如一個大而全的系統效率高。

6. 沒有服務治理,微服務數量多了後管理混亂

信奉微服務理念的設計人員總是強調微服務的 lightweight 特性,並舉出 ESB 的反例來證明微服務的優越之處。但具體實踐後就會發現,隨著微服務種類和數量越來越多,如果沒有服務治理系統進行支撐,微服務提倡的 lightweight 就會變成問題。

針對這些問題,我來介紹一下微服務架構最佳實踐的方法。

服務粒度

針對微服務拆分過細導致的問題,我建議基於團隊規模進行拆分。我認為微服務拆分粒度的「三個火槍手」原則,即 1 個微服務 3 個人負責開發。

3 個人負責開發一個系統,系統的複雜度剛好達到每個人都能全面理解整個系統,又能夠進行分工的粒度。

從團隊管理來說,3 個人可以形成一個穩定的備份,即使 1 個人休假或者調配到其他系統,剩餘 2 個人還可以支撐。

從技術提升的角度來講,3 個人的技術小組既能夠形成有效的討論,又能夠快速達成一致意見。

「三個火槍手」的原則主要應用於微服務設計和開發階段,如果微服務經過一段時間發展後已經比較穩定,處於維護期了,無須太多的開發,那麼平均 1 個人維護 1 個微服務甚至幾個微服務都可以。當然考慮到人員備份問題,每個微服務最好都安排 2 個人維護,每個人都可以維護多個微服務。

拆分方法

基於「三個火槍手」的理論,我們可以計算出拆分後合適的服務數量。根據目的的不同靈活地選取不同的拆分方式。接下來我一一介紹常見的拆分方式。

1. 基於業務邏輯拆分

這是最常見的一種拆分方式,將系統中的業務模塊按照職責範圍識別出來,每個單獨的業務模塊拆分為一個獨立的服務。

基於業務邏輯拆分雖然看起來很直觀,但在實踐過程中最常見的一個問題就是團隊成員對於「職責範圍」的理解差異很大,經常會出現爭論,難以達成一致意見。例如:假設我們做一個電商系統,第一種方式是將服務劃分為「商品」「交易」「用戶」3 個服務,第二種方式是劃分為「商品」「訂單」「支付」「發貨」「買家」「賣家」6 個服務,哪種方式更合理,是不是劃分越細越正確?

導致這種困惑的主要根因在於從業務的角度來拆分的話,規模粗和規模細都沒有問題,因為拆分基礎都是業務邏輯,要判斷拆分粒度,不能從業務邏輯角度,而要根據前面介紹的「三個火槍手」的原則,計算一下大概的服務數量範圍,然後再確定合適的「職責範圍」,否則就可能出現劃分過粗或者過細的情況,而且大部分情況下會出現過細的情況。

例如:如果團隊規模是 10 個人支撐業務,按照「三個火槍手」規則計算,大約需要劃分為 4 個服務,那麼「登錄、註冊、用戶信息管理」都可以划到「用戶服務」職責範圍內;如果團隊規模是 100 人支撐業務,服務數量可以達到 40 個,那麼「用戶登錄「就是一個服務了;如果團隊規模達到 1000 人支撐業務,那「用戶連接管理」可能就是一個獨立的服務了。

2. 基於可擴展拆分

將系統中的業務模塊按照穩定性排序,將已經成熟和改動不大的服務拆分為穩定服務,將經常變化和迭代的服務拆分為變動服。穩定的服務粒度可以粗一些,即使邏輯上沒有強關聯的服務,也可以放在同一個子系統中,例如將「日誌服務」和「升級服務」放在同一個子系統中;不穩定的服務粒度可以細一些,但也不要太細,始終記住要控制服務的總數量。

這樣拆分主要是為了提升項目快速迭代的效率,避免在開發的時候,不小心影響了已有的成熟功能導致線上問題。

3. 基於可靠性拆分

將系統中的業務模塊按照優先順序排序,將可靠性要求高的核心服務和可靠性要求低的非核心服務拆分開來,然後重點保證核心服務的高可用。具體拆分的時候,核心服務可以是一個也可以是多個,只要最終的服務數量滿足「三個火槍手」的原則就可以。

這樣拆分帶來下面幾個好處:

避免非核心服務故障影響核心服務

核心服務高可用方案可以更簡單

能夠降低高可用成本

4. 基於性能拆分

基於性能拆分和基於可靠性拆分類似,將性能要求高或者性能壓力大的模塊拆分出來,避免性能壓力大的服務影響其他服務。常見的拆分方式和具體的性能瓶頸有關,可以拆分 Web 服務、資料庫、緩存等。例如電商的搶購,性能壓力最大的是入口的排隊功能,可以將排隊功能獨立為一個服務。

以上幾種拆分方式不是多選一,而是可以根據實際情況自由排列組合,例如可以基於可靠性拆分出服務 A,基於性能拆分出服務 B,基於可擴展拆分出 C/D/F 三個服務,加上原有的服務 X,最後總共拆分出 6 個服務(A/B/C/D/F/X)。

基礎設施

大部分人主要關注的是微服務的「small」和「lightweight」特性,但實際上真正決定微服務成敗的,恰恰是那個被大部分人都忽略的「automated」。為何這樣說呢?因為服務粒度即使劃分不合理,實際落地後如果團隊遇到麻煩,自然會想到拆服務或者合服務;如果「automated」相關的基礎設施不健全,那微服務就是焦油坑。

微服務基礎設施如下圖所示:

看到上面這張圖,相信很多人都會倒吸一口涼氣,說好的微服務的「輕量級」呢?都這麼多基礎設施還好意思說自己是「輕量級」,感覺比 ESB 還要複雜啊?

確實如此,微服務並不是很多人認為的那樣又簡單又輕量級。要做好微服務,這些基礎設施都是必不可少的,否則微服務就會變成一個焦油坑,讓業務和團隊在裡面不斷掙扎且無法自拔。因此也可以說,微服務並沒有減少複雜度,而只是將複雜度從 ESB 轉移到了基礎設施。你可以看到,「服務發現」「服務路由」等其實都是 ESB 的功能,只是在微服務中剝離出來成了獨立的基礎系統。

雖然建設完善的微服務基礎設施是一項龐大的工程,但也不用太過灰心,認為自己團隊小或者公司規模不大就不能實施微服務了。第一個原因是已經有開源的微服務基礎設施全家桶了,例如大名鼎鼎的 Spring Cloud 項目,涵蓋了服務發現、服務路由、網關、配置中心等功能;第二個原因是如果微服務的數量並不是很多的話,並不是每個基礎設施都是必須的。通常情況下,我建議按照下面優先順序來搭建基礎設施:

服務發現、服務路由、服務容錯:這是最基本的微服務基礎設施。

介面框架、API 網關:主要是為了提升開發效率,介面框架是提升內部服務的開發效率,API 網關是為了提升與外部服務對接的效率。

自動化部署、自動化測試、配置中心:主要是為了提升測試和運維效率。

服務監控、服務跟蹤、服務安全:主要是為了進一步提升運維效率。

以上 3 和 4 兩類基礎設施,其重要性會隨著微服務節點數量增加而越來越重要,但在微服務節點數量較少的時候,可以通過人工的方式支撐,雖然效率不高,但也基本能夠頂住。

以上內容節選自李運華新書《從零開始學架構》——教你系統地學習架構實戰。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

GitHub已完全棄用jQuery,問題是為什麼?
Facebook開發出可自動掃描代碼找Bug的工具;中國發布自己的域名系統基礎軟體 「紅楓」;HHVM將停止支持PHP丨Q新聞

TAG:InfoQ |