微服務架構深度解析與最佳實踐 - 第三部分:微服務的使用場景和相關問題

微服務架構深度解析與最佳實踐 - 第三部分

微服務架構不是銀彈

 

《管理的常識》一書裏說,管理的核心是不斷的解決(推進工作過程中出現的各種)問題。同樣地,我認爲架構的核心則是不斷的解決(系統設計實現與演化過程中的各種)問題。

 

Fred Brooks 在《人月神話》裏說,“沒有銀彈”,現在依然成立,微服務也並不是只有優點,沒有副作用,把系統拆分了了很多部分,每一個部分簡單了,但是整體的關係變複雜了。前面介紹了那麼多微服務的特點和優勢,以及相關技術,我們再來分析一下微服務存在的問題,進而討論什麼場景適合使用微服務,什麼場景不適合,以及最佳的實踐方式。

 

 

微服務架構首先是一個分佈式系統架構。分佈式系統的發展由來已久,但是近年來產生了理論和實現的大爆發。

 

究其原因:分佈式系統的發展得益於廉價 pc 硬件使得堆機器成爲可能,而單機的成本/容量是非線性的,所以分佈式的核心是線性的水平擴展整個集羣的功能,以及帶來的協調機制,管理複雜度,數據和狀態一致性,容錯和故障恢復,容量與彈性伸縮,這些通用性的基礎能力建設。

 

簡單的翻譯一下:單個機器堆資源,升級 CPU 內存加大一倍,想要增加一倍的處理能力且成本不超過一倍,不僅很難、而且不現實了。這樣,我們就需要思考怎麼通過進一步對於系統裏不同功能的部分,拆解開,單獨擴展這些能水平擴展的部分,從而在控制成本的前提下,提升整個系統的處理能力。

 

另外,我們現在都知道,設計系統如果對可靠性,可用性有非常高的要求,那麼需要先假設上下游都是不可靠的,依賴的基礎設施和網絡也是不可靠的,這樣就考慮分佈式後的分片、複製、故障轉移、災難恢復等,分佈式系統下,我們可以對系統的不同性質的節點、不同可靠性可用性要求的組件,做針對性的單獨處理。

 

很多系統看起來是分佈式的,其實是一個大單機。 很多系統看起來是微服務的,其實是一個大單體。

 

就像人月神話裏說的,往已經延期的項目,加人手,可能會導致更延期。問題不是出現在應不應該加人,或者應不應該使用分佈式上。而是實施的人,沒搞清楚關鍵。比如系統拆成分佈式或微服務,然後某個關鍵地方依然卡住了業務流程,可能整體還不如單機的,擴展性失效,多加機器還不如單機。

 

爲什麼?

 

因爲如果希望用多個機器來擴展業務,最後發現各個機器上運行的程序沒有劃清楚邊界職責,多個機器合起來並不比單個機器有更大處理能力,這就是一個大單機。

 

同樣的,如果我們拆分了很多更小獨立的服務,但是一個業務請求進來,還是在一些地方被卡住,導致有一些瓶頸使得整個拆分後並不比之前有整體的改進,那麼其實是費勁的做了一個大單體系統。

 

所以合理的拆分微服務,使得我們能夠更好的擴展系統是關鍵,同時如果業務簡單,流量不大,不擴展也可以很好的應對,系統對於可用性和一致性要求也不是特別高,那麼分佈式和微服務,也不是必須的。

微服務系統適合的場景

以下幾類系統,比較適合使用微服務架構,或者使用微服務架構改造:

 

  • 大型的前後分離的複雜業務系統後端,業務越複雜,越需要我們合理的設計和劃分,長期的維護成本會非常高,歷史包袱也很重,這個問題後面會詳談。

  • 變化發展特別快的創新業務系統,業務快,就意味着天天要“擁抱變化”,每一塊的業務研發都要被業務方壓的喘不過氣,不做拆分、自動化,一方面研發資源永遠不夠用,活永遠幹不完,另一方面不停的在給系統打補丁,越來質量越低,出錯的可能性也越來越大。

  • 規劃中的新大型業務系統,如果有能力一開始就應該考慮做微服務,而不是先做單體,還是發展到一定的階段再做改造,改造一定是傷筋動骨的大手術,雖然我們可以採取一些策略做得更平滑,但是成本還是比較高的。

  • 敏捷自驅的小研發團隊,擁抱新技術,可以直接用微服務做系統,不但的通過快速迭代、持續交付,經過一定時間的嘗試和調整,形成自己的微服務實踐經驗,這樣在團隊擴大時可以把好的經驗複製到更大的團隊。

 

反過來,以下幾類系統,不太適合一開始就做微服務:

 

  • 小團隊,技術基礎較薄弱,創業初期或者團隊新做的快速原型,這個時候做微服務的收益明顯比單體要低,快速把原型做出來怎麼方便怎麼來,用團隊最熟悉的技術棧。

  • 流量不高,壓力小,業務變化也不大,單體能簡單搞定的,就可以先不考慮微服務,不考慮分佈式,因爲分佈式和微服務帶來的好處,可能還不足以抵消複雜性增加帶來的成本。

  • 對延遲很敏感的低延遲高併發系統,低延遲的祕訣就是離 io 能多遠就多遠,離 cpu 能多近就多近,分佈式和微服務,導致增加了網絡跳數,延遲就沒法降低。

  • 技術導向性的系統,技術產品,這類產品跟業務系統不同,常規的業務系統研發方法不是太適合。

微服務帶來的一些問題

 

Chris Richardson 在文章(http://blog.daocloud.io/microservices-1/)裏提到了微服務的幾個不足:

 

  • 服務大小:『微服務』強調了服務大小,有人強調服務要大一點,也有人願意採用小服務。需要注意這只是一種選擇,微服務的目的是有效的拆分應用,實現敏捷開發和部署。

  • 進程通訊:微服務應用是分佈式系統,由此會帶來分佈式固有的複雜性。開發者需要在 RPC 或者消息傳遞之間選擇並完成進程間通訊機制。相對於單體式應用中通過語言層級的方法或者進程調用,微服務下這種技術顯得更復雜一些,需要考慮 RPC 的超時、重試、失效策略,或者消息服務不可用,堆積堵塞等問題。

  • 數據庫拆分:數據庫事務對於單體式應用來說很容易,因爲只有一個數據庫。在微服務架構應用中,需要更新不同服務所使用的不同的數據庫。使用分佈式事務並不一定是好的選擇,不僅僅是因爲 CAP 理論,還因爲很多中間件並不支持這一需求。最終你不得不使用一個最終一致性的方法,從而對開發者提出了更高的要求和挑戰。

  • 測試複雜度:比如採用流行的 Spring Boot 架構,對一個單體式 web 應用,測試它的 REST API,是很容易的事情。反過來,同樣的一個業務場景,需要測試啓動和它有關的所有服務,這些服務在不同的進程,所以變得尤爲複雜。

  • 服務依賴關係:微服務架構模式應用的改變將會波及多個服務。比如,假設你在完成一個案例,需要修改服務 A、B、C,而 A 依賴 B,B 依賴 C。在單體式應用中,你只需要改變相關模塊,整合變化,部署就好了。對比之下,微服務架構模式就需要考慮相關改變對不同服務的影響。比如,你需要更新服務 C,然後是 B,最後纔是 A,幸運的是,許多改變一般隻影響一個服務,而需要協調多服務的改變很少。特別是,如果要處理的服務間依賴是一個網狀關係,那麼很可能導致,我們修改 A 時,考慮到了會影響 BCDEF 這幾個服務,但是漏掉了影響系統 K,導致上線以後發現 K 的部分功能無法使用了。

  • 部署複雜度:部署一個微服務應用也很複雜,一個分佈式應用只需要簡單在負載均衡服務後面部署各自的服務器就好了。每個應用實例是需要配置諸如數據庫和消息中間件等基礎服務。而一個微服務應用一般由大批服務構成。例如,根據 Adrian Cockcroft,Hailo 有 160 個不同服務構成,NetFlix 有大約 600 個服務。每個服務都有多個實例。這就造成許多需要配置、部署、擴展和監控的部分,除此之外,你還需要完成一個服務發現機制,以用來發現與它通訊服務的地址(包括服務器地址和端口)。傳統的解決問題辦法不能用於解決這麼複雜的問題。接續而來,成功部署一個微服務應用需要開發者有足夠的成熟部署方法,並高度自動化。

 

Peter Lawyer 有在一篇文章裏(https://vanilla-java.github.io/2016/03/22/Micro-services-for-performance.html) 中也提出,微服務的幾個問題:

 

  • 服務形成信息障礙。

  • 引入了額外的複雜性和新問題,例如網絡等待時間,消息格式,負載平衡和容錯。忽略其中之一屬於“分佈式計算的謬誤”。

  • 測試和部署更加複雜。

  • 整體應用程序的複雜性僅轉移到網絡中,但仍然存在。

  • 細粒度的微服務已被批評爲一種反模式。

 

其實可以看到,大家的想法和分析都比較一致,微服務架構帶來的固有複雜性和人爲複雜性如何管理:

 

  1. 如何合理拆分微服務,粒度如何控制:對業務按粒度和邊界拆解的問題,這決定了我們的服務是不是合理,開發和維護是不是方便。核心思路是深入瞭解業務。

  2. 遺留系統應該如何改造,從哪兒下手,如何推動:改造遺留系統一般來說比重新做一個新系統更復雜,如何平滑的、最大代價的將老系統改造成微服務,也是一個巨大挑戰。

  3. 拆分後的性能應該如何保障:性能有兩個指標,關鍵是區分出來如何處理不同特性的數據,關注不同的指標,做好優化和選型,針對具體細節具體對待。

  4. 怎麼考慮拆分後的數據一致性,分佈式事務的選取和取捨:多個服務間的業務數據一致性的問題,事務是個需要重點考慮的問題,主要是考慮強一致性的分佈式事務還是可以使用最終一致的弱一致性。對於一般的業務,可能使用補償衝正類的做法,在業務允許的一定時間內數據達到一致狀態即可,比如 30s,或者 10 分鐘。

  5. 系統和服務的高可用可伸縮如何實現:高可用意味着系統穩定健壯,可伸縮意味着彈性,資源有效使用,如何做到無狀態、不共享,是實現可高用可伸縮的關鍵。

  6. 拆分過程的測試和部署如何處理,怎麼提升管理能力,降低風險:跨系統的協作問題、測試的問題,這對於技術能力和研發成熟度較低的團隊,會帶來很大麻煩。核心思路定義好業務邊界、系統間接口與數據標準,提升自動化測試水平。微服務架構由於拆分粒度較細,測試是個大問題。在保持每塊職責單一的同時,關鍵是保證接口穩定,做好自動化測試(特別是 UT 和接口的自動化)和持續集成,儘量少全流程的人工迴歸測試。部署單元太多導致維護成本上升的問題,要管理的點多了,問題自然複雜了,核心思路是自動化部署與運維。

  7. 拆分後的運維和監控如何處理:怎麼應對系統的故障,關鍵是保障核心技術的指標,以及業務指標,做好預警報警,積累問題、尋找根因,控制和杜絕低級失誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章