微服務架構下的核心話題 (二):微服務架構的設計原則和核心話題

 

前期回顧:

微服務架構下的核心話題 (一):微服務架構下各類項目的順勢崛起

一、前言

     毫無疑問,微服務架構的設計原則和核心話題是本文要討論的重點,也是打算從零基礎開始構建微服務架構需要事先考慮、規劃的。一個好的產品、應用能否穩定運行,持續開發,滿足業務需求,能否經得起現實的考驗,就需要在設計階段考慮很多、很多,以確保它的健壯性。

    當我們從單體架構的應用走向基於微服務的架構時,首先會面臨一個很棘手的問題是如何進行服務的拆分,服務的拆分粒度應該如何衡量,怎樣拆分的服務纔算是“微”。接着將又會面臨,這麼多的服務又如何關聯起來呢?如何有效的相互間通信呢?如何高效的部署呢……

     本文我將從微服務架構的設計原則、核心話題兩大方面展開討論,希望能夠對你構建一個微服務架構的應用有所幫助。

 

二、微服務架構的設計原則

      軟件架構的設計原則、方法論,在很大程度上能夠指導、提醒我們應該遵循什麼的原則、規範,能讓軟件架構更加健壯、穩固,並易於開發、擴展、維護等。

1.拆分足夠微

     在解決複雜的問題時,我們傾向於將問題劃分成若干個小問題來解決,所謂“大事化小,小事化了”。單體架構的應用,隨着時間的推移,會變得越來越臃腫,越來越難以維護,適當的做“減法”,可以解決單體架構存在的這些問題。

     將單體架構的應用拆分爲微服務架構的應用時,服務的拆分粒度問題,成爲了重中考慮的問題。粒度太大,拆分的不夠充分,便和單體架構沒有太大的區別,更不能發揮出微服務的優勢。如果拆分的太細,又將會面臨着服務數量太多而引發的服務管理、服務間調用的問題。對於如何“微”纔算是足夠的“微”,是沒有標準的衡量計算方法的。

    微服務不是說越小越好。服務越小,微服務架構的優點和缺點也就會越來越明顯。服務越小,微服務的獨立性就越高,但同時微服務的數量也會增加,管理就會存在很大的問題,成爲一個新的挑戰,這也就是常常所被提到的“這麼多的服務,該服務管理啊?”問題。

    服務的拆分足夠微,可以按照某種方式、規則拆分,通常可以按照業務模塊、業務場景等進行拆分,儘量避免服務間的相互依賴,做到高內聚低耦合。緊密關聯的處理,放在一個服務內,但避免在服務與服務之間共享數據。

2.輕量級通信

      在單體架構的應用中,可直接通過簡單的方法調用就能進行通信,但在微服務架構中,由於服務都是跨域進程,甚至是跨主機的,組件只能通過REST、Web服務或RPC類似的機制在網絡上進行通信。

      因爲服務劃分的已經足夠小了,服務間的通信可能會比較頻繁,考慮到性能、響應時間等方面,則服務間通信應採用輕量級的通信協議,如:同步的REST,異步的AMQP、STOMP、MQTT等。在實時性要求不高的場景下,採用REST通信是不錯的選擇,REST是基於HTTP協議,可方便進行跨域訪問或跨防火牆的設置,並且消息格式可以統一爲XML或JSON格式,方便開發人員閱讀和理解。如果服務間通信比較頻繁,有比較高的要求,可採用消息通信的方式,如:Kafka、MQ等類似的消息中間件。如果不考慮對外提供訪問的話,可採用gRPC的通信方式,因爲gRPC是基於Netty的,通信效率更高。

3.單一職責原則

     當服務粒度過粗時,服務內部很容易產生耦合。如果多人開發同一個服務,很容易因爲耦合過大造成代碼修改重合,不利於後期維護。確保每個服務職責單一,這也是用來確定服務拆分邊界的一個原則,遵循“高內聚、低耦合”。

    必須要對自己的產品和業務的瞭解,才能更準確的確定服務邊界,讓各個服務滿足單一的業務職責,避免職責交叉。

4.領域驅動原則

     領域驅動設計(Domain Driven Design),是一套綜合軟件系統分析和設計的面向對象建模方法。一個微服務,就應該能夠反映出某個業務的領域模型,使用領域驅動設計,不但可以降低微服務環境中通用語言的複雜度,而且可以幫助團隊搞清楚領域的邊界,理清上下文邊界。

    建議將每個微服務都設計成一個DDD限界上下文,爲微服務提供了一個邏輯邊界。每個獨立的團隊負責一個邏輯上定義好的系統切片,負責與一個領域或業務功能相關的全部開發,最終團隊開發出的代碼更加易於理解和維護。

(關於DDD更詳細的瞭解,可參考https://www.cnblogs.com/edisonchou/p/edc_ddd_foundation_study_part1.html)

 

三、微服務架構的核心話題

      基於微服務架構的應用,將面臨着許多選擇、爭議等討論的核心話題,這些核心話題將會在你接下來的微服務架構生涯裏不斷出現,併成爲討論的焦點。在此,我覺得有必要進行彙總整理,讓你覺得它存在的必要性,能爲你之所用。

1.服務拆分

       服務拆分首先關注的就是服務的顆粒度,可遵循設計原則——拆分足夠微,通過DDD(領域驅動設計)的指導,將某個領域的功能進行聚合成爲一個服務。

       對於一個大型複雜的單體應用而言,選擇先拆分哪個模塊,是一個問題。一般考慮先從容易、簡單被拆分的模塊開始,在拆分簡單模塊過程中,不斷積累微服務的經驗,逐步拆分掉複雜、繁重業務的核心模塊。同時,尋找那些和其他功能業務重合度低、耦合度低,且自身變化較爲緩慢的基礎服務,將它們拆分爲微服務。

      決定了拆分哪些模塊,要拆分成多個微服務後,接下來就要劃清服務拆分的邊界,將服務邊界和接口順理清楚。確定哪些應該包含進來,哪些不應該包含進來,哪些接口需要重新設計,哪些可以重複利用。

      如下圖所示,展示了一個單體應用拆分爲多個微服務的過程。一旦拆分完後,各個服務就可以獨立開發、部署和擴展。

     服務的拆分,不單單指功能的拆分,如上圖所示,還得考慮數據庫的拆分 ,確保降低功能邏輯層、數據訪問層的耦合度。

2.服務註冊與發現

      微服務架構的特點是服務的數量衆多,這些衆多的服務需要一個統一的服務註冊平臺來進行服務的管理。每個微服務實例在啓動後,將自己的實例信息註冊到服務註冊表或服務註冊中心。服務的調用方若想獲取可用服務實例的列表,則需要從服務註冊表中去獲取相關的信息。

      當服務實例失效或down掉以後,服務實例的信息就要從服務註冊表中移除,即:服務註銷。服務註冊表是用於維護所有可用的服務實例的地方,服務註冊表一方面要接收微服務實例的接入,另一方面當服務實例不可用時,需要及時將服務實例從註冊表中清楚。下圖展示了服務註冊與服務實例的關係。

       服務註冊與發現組件或框架,有很多,如:Eureka、Consul、etcd等,都提供了服務註冊表的功能,可供大家進行選擇。

3.負載均衡

       在微服務架構中,負載均衡是必須使用的技術,通過它來實現系統的高可用、集羣擴容等功能。負載均衡通常分爲兩種:服務端負載均衡和客戶端負載均衡。通常所說的負載均衡均指服務器端的負載均衡,可通過軟件或硬件設備來實現,軟件如:Nginx、LVS等,硬件如:F5、A10等,硬件負載均衡設備成本較高,大部分採用的是軟件方式。架構圖如下:

       通過軟件或硬件實現負載均衡都會維護一個服務端清單,利用心跳檢測等手段進行清單維護,保證清單中都是可以正常訪問的服務節點。當用戶發送請求時,會先到達負載均衡器(一般作爲一個服務),負載均衡器根據負載均衡算法(輪訓、隨機、加權輪訓)從可用的服務端列表中取出一臺服務端的地址,接着進行轉發,降低系統的壓力。

4.API網關

       考慮到微服務架構中服務的數量很多,爲了便於服務對外統一的管理,API網關的引入是必不可少的。API網關旨在提供統一的API入口點,來管理多個服務內部API,可方便實現對平臺衆多服務接口進行管控,如對訪問服務的身份認證、業務鑑權、流量併發控制、API調用的計量或計費等。

      API網關常用於以下場景:

  • 黑白名單:實現例如通過IP地址來禁止訪問某些服務的某些功能。
  • 日誌:實現日誌訪問的記錄,用於分析訪問、處理性能指標,並將分析結果提供給其他模塊使用,如:運維平臺的統計功能。
  • 協議適配:實現通信協議校驗、適配轉換的功能。
  • 身份認證:負責外部系統的訪問身份認證。
  • 計流限流:實現微服務訪問流量計算,基於流量計算分析進行限流等。
  • 路由:API網關的核心功能,實現請求的轉發。

     API網關的引入爲微服務架構應用帶來諸多的好處,如下:

  • 避免將內部信息/接口泄露給外部: 能夠將對外發布的API與微服務內部的API區分開來,使得各個微服務在添加或變更時,能有明確的安全邊界,避免多過的對外暴露。
  • 爲微服務添加額外的安全層:能夠提供一套額外的保護層,用以應對SQL注入、Dos攻擊等,其中系統的權限控制可以再這一層來實施。
  • 支持多種混合通信協議:考慮到微服務架構中,各個微服務的平臺與語言的多樣性,通常將對外提供基於HTTP或REST的API接口,而內部微服務將根據自身服務情況採用不同的通信協議(如:ProtoBuf、RPC等)。API網關則跨域這些內部不同協議的微服務,提供一個基於REST的統一外部API。
  • 減低構建微服務的複雜性:基於微服務架構應用的複雜性,如API令牌、訪問控制、限速限流等,每一項功能的添加,對會額外對各個服務帶來影響,從而影響微服務的開發週期。這些功能如果在API網關上統一處理,則會從代碼層面進行了有效的隔離,使得不會影響其他微服務,這樣更有利於其他微服務只需關注於實際的業務開發。

    常見的API網關實現方式很多,如:Nginx、Kong、Spring Cloud Zuul、Træfɪk等。

5.服務部署與發佈

     單體應用被拆分爲微服務後,隨着微服務的數量增多,部署就成了問題,使得部署的複雜性提高了不少。所以,微服務的部署更加傾向於使用具有相互之間隔離的主機/虛擬機來實現服務的部署,使得服務能夠獨立的部署、測試、發佈、升級。

    目前比較好的服務部署方式就是把各個微服務打包成Docker鏡像,這樣就保障避免了不同主機環境對部署產生的影響。使用Docker部署,並結合Jenkins進行CI/CD,使得構建、發佈、啓動變得更加快捷。

    下圖就是服務部署、發佈流程。

 

四、總結

       一個微服務架構的應用,從最初的設計到逐步成型,是需要經過不斷的迭代開發、摸索來完善的,上述只是列舉出了我個人認爲需要重點關注的點,以供大家參考,如有遺漏不足,望大家建議補充、完善。

 

歡迎微信掃碼下面二維碼,關注微信公衆號【程序猿技術大咖】,進行更多交流學習!

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