如何構建微服務架構

【編者的話】「微服務」的概念興起於四五年前,近幾年尤爲火熱,各大廠都在進行微服務化改造和微服務建設。最近一年來咱們也參與了微服務化的改造大軍,這裏寫下一些作微服務系統設計和開發時的切身感覺。html

【3 天燒腦式基於Docker的CI/CD實戰訓練營 | 北京站】本次培訓圍繞基於Docker的CI/CD實戰展開,具體內容包括:持續集成與持續交付(CI/CD)概覽;持續集成系統介紹;客戶端與服務端的 CI/CD 實踐;開發流程中引入 CI、CD;Gitlab 和 CI、CD 工具;Gitlab CI、Drone 的使用以及實踐經驗分享等。java

微服務架構

提及微服務,不得不提那篇經典的文章,來自Martin Flower的《Microservices》,建議多讀幾遍。Martin Flower是敏捷開發方法創始人之一,《重構》《企業應用架構模式》做者,ThoughtWorks公司的首席科學家。微服務雖然不是在這篇文章中首次提出,可是它將發展多年的微服務架構進行了重要性總結,推進了微服務的流行。數據庫

Martin在文章中從多個方面詳細闡述了微服務的概念,首先做者對比單體應用的架構,一個單體應用處理請求的全部邏輯都運行在一個單獨的進程中,這種狀況下,你能夠在筆記本上開發、測試、部署都很簡單,還能夠經過負載均衡進行橫向擴展,最後交付給運維團隊。單體應用很是成功,可是愈來愈多的人感受不妥,尤爲是在雲中部署的時候,任何微小的變動都要總體從新構建和部署,擴展的時候也須要總體擴展,不能進行部分擴展。這時候微服務架構風格就出現了,它提出將應用程序構建爲一套服務,每一個服務均可以獨立部署和擴展,運行在獨立的進程中,服務之間經過RPC調用進行通訊。微服務的應用致力於鬆耦合和高內聚:採用單獨的業務邏輯封裝,接受請求、處理業務邏輯、返回響應,並且喜歡簡單的REST風格,而不喜歡複雜的協議,最終實現敏捷開發。 後端

單體架構和微服務架構圖

微服務不是什麼框架,也不是什麼系統,只是一種架構風格。咱們所使用的DSF(華爲)、DUBBO(阿里)、Spring Clould(Pivotal)等框架,在介紹中都稱是分佈式服務框架。這些分佈式服務框架都是微服務架構必不可少的基礎能力,微服務必定是分佈式的。分佈式服務的概念比較模糊,只是解決了網站的高併發問題,不少細節問題是微服務幫其明確的。微服務更增強調敏捷和健壯,強調服務的粒度,一個服務只需完成一個單一的、獨立的功能,多個微服務組合完成相對複雜的業務系統,以知足需求。並且微服務注重藉助於各類中間件進行業務解耦和提升性能,以及提升服務的容錯性。服務器

從上面的介紹中咱們能夠看出,微服務架構有不少優勢。例如,服務的拆分將複雜問題簡單化;每一個服務由專門的團隊開發,開發者能夠自由選擇實現技術,提供API服務;每一個微服務均可獨立部署,加快了部署速度;每一個服務可獨立擴展以知足需求。微服務不是免費的午飯,微服務架構也有缺點。微服務概念強調了服務的大小,可是服務變小不是最終目的,微服務的目的是有效地拆分應用,實現敏捷開發和部署;微服務應用都是分佈式系統,須要經過RPC進程間通訊完成服務調用,這樣大大增長了系統的複雜性,所以必須寫代碼處理因爲網絡或者服務不可用等致使的調用失敗問題,雖然通常框架都支持相關配置,可是在這種狀況下微服務顯得相對複雜些;在微服務架構的應用中,建議不一樣的服務使用不一樣的數據庫,這種狀況下,一個交易通常會調用多個服務,同時須要修改多個數據庫,因爲CAP理論和其它的一些因素,並不能實時地保證數據的一致性,所以不得不使用最終一致性的方法,從而對開發者提出了更高的要求和挑戰;測試一個微服務架構的應用也是很複雜的任務,首先須要啓動和它相關的全部服務(至少須要這些服務的stubs)。最後仍是要強調一下,不要低估了微服務架構帶來的複雜性,下面介紹一下咱們如何應對這樣的複雜性。網絡

微服務架構給咱們帶來方便的同時,也引入必定的系統複雜性,最近幾年隨着基礎設施自動化技術的發展,好比雲平臺、容器技術,再加上自動化測試與持續集成,減小了構建、發佈、運維微服務的複雜性。所以咱們的微服務團隊應該依賴基礎設施自動化技術構建軟件,下圖說明這種構建的流程: 架構

基本的構建流程

在構建微服務軟件時使用的分佈式服務框架也擁有不少特性,這些特性提供了不少複雜問題的解決方案,好比異步調用、超時失敗策略、故障隔離、健康檢查、流量控制以及自定義路由等,這些特性大大減輕了開發者處理邏輯的負擔,還有一些高性能、高可用的保障都增長了咱們構建微服務的信心。並且通過多年的微服務實踐者的摸索,也總結出了不少輔助運維繫統,好比統一日誌收集(ELK)、服務管理、服務監控和服務治理等,大大減輕了運維的工做,並且能讓咱們對複雜的微服務系統作到心中有數。併發

總之,微服務架構入坑容易,坑了呆得舒服難。各類基礎設施和配套系統必須跟得上,還得有一個具備微服務特性的團隊,才能真正駕馭得了微服務。負載均衡

兩個值得深刻的話題:框架

  1. 微服務與持續集成
  2. 微服務與測試

微服務團隊

上一節中說到更適合構建微服務應用的微服務團隊,什麼時微服務團隊?說一個比較現實的問題,當咱們作服務拆分的時候,一般管理都會集中在技術層面,涉及到UI團隊、服務端業務邏輯團隊、數據庫團隊、測試團隊和運維團隊。當採用這種標準對團隊進行劃分時,即便時小小的變動都將致使跨團隊項目協做,從而消耗時間和預算審批。這就是 Conway's Law :

設計一個系統的任何組織(廣義上)都會產生這樣一種設計,其結構是組織交流結構的複製。 ——Melvyn Conway, 1967

Melvyn Conway 的意思是設計一個系統的團隊結構將決定了一個軟件系統的結構,將人員劃分爲 UI 團隊,中間件團隊,DBA 團隊,那麼相應地,軟件系統也就會天然地被劃分爲 UI 界面,中間件系統,數據庫。而一個高效的微服務團隊會針對這種狀況進行改善,微服務團隊須要是一個全棧的團隊,跨職能的團隊,應該包含整個項目週期的全部技能,先後端開發、UI設計、測試、構建部署、上線與運維都是必須技能。

微服務團隊除了熟練的業務邏輯開發以外,還須要有DevOps能力、服務的快速構建、良好的團隊文化:

  • 首先DevOps能力是保證持續交付和應對複雜運維問題的動力之源,運維人員不懂開發人員的服務設計和調用流程,開發人員不懂產品環境和總體配置結構,開發和運維的融合才能更好的應對微服務架構。正以下面這句話所說的,「你構建,你運維」。

You build it, you own it. – Amazon CTO

所以,須要打造DevOps文化,將運維做爲需求提早注入到開發流程中。

DevOps流程

  • 其次保持服務的持續演進,使服務可以快速、低成本地被拆分和合並,以快速響應業務的變化。

  • 同時要保持團隊和架構的對齊,微服務看似是技術層面的變革,但它對團隊結構和組織文化有很強的要求和影響,識別和構建匹配架構的團隊是解決問題的加速器。微服務團隊的另外一個關鍵點是持續改進、持續學習和反饋,只有保持這樣一個文化氛圍,微服務架構才能持續發展下去,保持新鮮的生命力,進而實現咱們的初衷。

專業的微服務團隊,爲微服務保駕護航。

項目的微服務設計實踐

咱們在各類基礎設施不健全的狀況下,匆忙進入了微服務改造的深淵。原來的單體應用按照功能拆分紅了下面的結構:

微服務下的系統分層

拆分以後,模塊忽然變多了。將內部業務邏輯和原子功能拆分出來,實現了部分功能的複用,而且對外的接口按類型區分到不一樣的模塊中去了,方便了使用,可是增長了管理的難度。

從上面咱們對微服務架構的瞭解,一個微服務系統會有大量的服務組成,服務之間的層次關係依然是存在的,可是調用順序上的要求會有所下降,只要知足嚴格的上層調用下層便可,在某些簡單的業務功能上容許跨層調用。

架構對比圖

上圖是三種架構(集中式、分佈式、微服務架構)的形象化展現。能夠看到微服務的一個狀態,乍看起來有些混亂,若是還按照之前的管理方式維護項目的話,工做量會成指數級增加,人力所沒法勝任的工做。

這時候就須要依賴一些分佈式服務框架,並創建一些輔助運維繫統:

  1. 首先服務之間遠程調用,服務的註冊和發現機制必須有好的分佈式服務框架(相似dubbo)支持,方便作服務之間的調用配置管理。
  2. 部署的服務進程增長之後,對應的日誌文件也會增多,這時再使用ssh到服務器上查看日誌,這個工做量也是可想而知的。咱們對業務日誌作了規範化約束,而後使用ELK技術棧搭建了日誌集中化管理系統。
  3. 爲了可以對線上的全部服務有個全局的把控,咱們根據註冊中心的數據搭建了服務的管理系統,展現各個維度的統計數據,例如,每一個主機上多少個應用,每一個應用提供了多少個服務,同時又消費了多少個服務等等。還有一些針對服務的約束規則的告警信息,例如某個應用消費的服務,卻沒有服務提供者等。還有一個總體的應用之間的依賴關係圖。
  4. 爲了優化系統結構和排查問題,搭建了服務的監控系統,這個是依賴分佈式服務框架打印的預統計日誌的,經過這些日誌分析獲得一個總體的服務監控功能,例如每一個服務的響應時間、錯誤率等。還有調用鏈跟蹤功能,排查問題時使用它來跟蹤請求信息。
  5. 服務治理功能用來及時地對線上項目作一些調整,例如限流、降級、負載均衡、超時、路由、隔離容錯等。

有了以上這些系統輔助,咱們的微服務化改造之路平坦了許多。

在進行微服務化改造的時候,接口的設計上遇到了一個問題,服務之間的調用是經過私有協議進行的RPC調用,這種調用中如何描述服務響應成功以外的其餘異常狀況?

  1. 採用Exception類,定義各類異常類來描述異常狀況。
  2. 採用錯誤碼+錯誤描述。

其中方案1採用的Exception類,是咱們平時java中定義進程內部接口最多見的方法,這種方法的優勢是,可以使調用接口的一方的代碼更簡潔,經過try...catch來處理,若是不須要處理的話,在方法上聲明直接向上拋出便可。缺點是跨語言開發解析難度大增,並且日誌中異常堆棧不少。方案2採用錯誤碼的形式偏偏相反,缺點就是每次調用都要判讀是否調用成功,增長代碼中的if語句。

針對這個問題,但願各位實踐分佈式服務或者微服務的大神給出大家的實踐方案,瘋狂討論起來。

結束語

上述三節中講述了咱們在構建微服務的經歷和一些感想,給其餘準備實施微服務和正在實施微服務的團隊以參考,寫這篇文章的另外一個目的就是但願能起到拋磚引玉的做用,但願能和其餘團隊進一步交流。

搞微服務

原文連接:如何構建微服務架構(做者:rabbitGYK)

相關文章
相關標籤/搜索