一、前言
隨著IT技術發展和推進,傳統的單體應用程序模式已不滿足大多數企業IT平臺構建,尤其是大型互聯網網站或企業級應用。單體應用隨著項目持續集成,代碼庫越來越大,在系統復雜度、測試、代碼沖突解決、可擴展性、多環境支持、需求變更容易造成系統整體影響等方面面臨各種嚴峻挑戰。此時微服務架構應運而生。
微服務從2014的1.0技術元年開始,隨著微服務社區的推進,微服務技術體系生態產生極大變化,微服務進入2.0時代。微服務架構體系經過多年的大規模生產驗證,已成為構建互聯網網站、大型企業級應用的首選分布式技術架構。
2020年隨著容器化、K8S技術的發展狀態,將微服務架構推向了更高的地位,甚至許多大廠都在喊著一些都是服務化的口號。現在后端工程師除了搞算法、嵌入式的外,簡歷上不寫著會微服務,大概也不好找工作了吧...
相對于單體應用,微服務更具有優勢:
- 易于理解:微服務將應用按照功能分解為獨立開發和部署的微型應用,每個服務與應用程序的其他微服務之間有一個很小且有限的契約。微服務更加專注目標,作為一個功能模塊的單元,微服務更容易理解。
- 微服務易于測試:每個微服務都是獨立開發部署的微型應用,易于測試。在集成測試和驗收測試方面也更易于驗證。
- 較少遇到庫不兼容問題:每個微服務都有自己獨立的項目構建依賴項的集合,而這些集合不會與其他微服務共享。
- 微服務能夠獨立擴展:微服務之間獨立部署,因此指定微服務的內存和實例擴展不會影響整體應用其他微服務的內存和實例數量。
- 微服務可以獨立選擇不同的技術棧:微服務可以選擇不同的語言、平臺、框架和庫。特別是如果微服務采用HTTP協議這樣的跨平臺協議,實際上java微服務可以和C#、Python等編寫的微服務協作是完全合理的。
- 微服務更易于發布:微服務是獨立部署的,因此不需要等待其他微服務部署就緒。同時隨著docker容器化、k8s服務編排、自動化CI/CD工具的出現,讓微服務的發布更加簡單。
當然微服務架構作為分布式架構,同樣面臨網絡延遲、多服務運維、分布式復雜性等問題的挑戰。因此合理合適的技術選型是微服務項目的構建的重中之中。
選型準則
生產級
我們使用微服務架構是要解決實際業務場景和生產抗流量的,而不是做簡單的demo,如果選擇不慎可能出現生產級事故。因此,生產級(Production Ready)、可運維(Ops Ready)、可治理、技術成熟的微服務技術才是我們的首選。
使用已經在多個一線互聯網或大型企業落地并經過生產挑戰的
我們應該盡量選擇使用已經在多個一線互聯網或大型企業落地并經過生產挑戰并且開源的,且在社區有良好口碑的技術棧。
開源社區活躍
社區活躍、stars數量越多、代碼和文檔更新頻率高的技術棧是優選選擇的,開源社區活躍可以直接反應技術的生命力。同時閉源或者停止更新的技術框架應該慎重選擇。
結合項目實際情況
不是所有項目都適用于微服務架構體系,應該結合項目實際情況選擇合適的技術架構。
二、微服務基礎架構關鍵
微服務框架選型
微服務框架經過多年發展是一個比較成熟的領域,有比較多選擇,以下為市場主流微服務架構對比:
微服務框架 | Spring Boot/Cloud | Dubbo/DubboXg | gRpc | Thirft | Motan |
---|---|---|---|---|---|
功能點位 | 完整微服務框架方案 | 服務框架 | RPC | RPC | RPC |
是否支持REST | 是,基于Ribbon支持多種可插拔的序列化選擇 | 否 | 否 | 否 | 否 |
是否支持RPC | 否 | 是 | 是 | 是 | 是 |
是否支持多語言 | 是 | 否 | 是 | 是 | 否 |
典型案例 | Netflix、阿里 | 阿里、當當 | 谷歌 | Sina | |
社區活躍 | 高 | 高 | 高 | 一般 | 一般 |
文檔豐富度 | 高 | 高 | 一般 | 一般 | 一般 |
Spring Cloud由于其Spring社區影響和Netflix的背書,以及其提供的完整一套微服務框架實現方案,目前可以認為Spring Cloud是基于java構建微服務的標準方案。其對于新興團隊或未形成自己微服務體系的團隊有較大吸引力。Spring Cloud由于其社區活躍度、完善的生態,目前國內外眾多大廠都加入其生態家族(aws、alibaba、huawei、Azure等),甚至阿里將其微服務框架Dubbo也加入到Spring Cloud生態,成為其畢業項目。
Spring Cloud框架本身基于HTTP協議,是一種典型的RESTfull框架而不是RPC框架,序列化協議主要基于文本的JSON。
RESTfull天然支持跨語言平臺,任何支持HTTP協議的應用都可以接入調用,但是客戶端需要自己解析payload。TESTfull框架接口文檔管理隨著版本迭代,維護越發困難,如果沒有統一標準的接口文檔管理機制,更新不及時或缺乏注釋等接口文檔對于接口調用者和繼續集成開發者來說是一個災難。目前Spring框架也支持Swagger 契約編程模型,可以基于Swagger 契約生成各語言的強類型客戶端,極大方便不同語言棧的接入。Dubbo是阿里多年構建生產級分布式微服務的技術結晶,服務治理能力豐富,在國內社區非常活躍。Dubbo其本質是一套基于java的RPC框架。當當DubboX在Dubbo基礎上進行了擴展,支持了RESTfull接口暴露的能力。
Dubbo主要面向Java技術棧,跨語言支持能力先天不足,同時由于豐富的治理能力,框架整體比較重,想要完整使用好Dubbo門檻比較高。但是如果企業基本都是基于java技術棧進行項目構建,選擇Dubbo可以使項目站在比較高的起點上,Dubbo在企業級性能和服務治理能力都非常優秀。Sina的Motan和Dubbo功能類似,可以認為是Dubbo的輕量級剪裁版。前面已說到Dubbo已加入Spring Cloud生態,通過Apache Dubbo RPC擴展Spring Cloud服務間調用的通信協議,因此一定程度可以不用糾結Spring Cloud還是Dubbo了 O(∩_∩)O。
gRpc是谷歌推出的一套RPC框架,基于protobuf的強契約編程模型,能夠自動生成各類語言的客戶端且保證互操作。gRpc適用于內部互相調用的場景,對外暴露RESTfull API實現比較麻煩,需要引入第二套RESTfull 框架作為輔助。
運行時服務支撐服務選型
服務注冊與發現
服務治理實現微服務架構體系下各個微服務實例的自動化注冊和發現。大部分分布式項目在構建之初,由于微服務實例較少,基本是采用傳統靜態配置的方式管理服務實例清單,在項目擴展或變更時需要手工維護靜態配置。隨著業務發展,系統功能越來越復雜、微服務實例數量也極具增加,手工方式維護靜態配置需要花費大量人力,同時還極易發生錯誤。服務治理組件就是為了解決微服務架構實例維護問題。
CAP原則
談到服務注冊就必須先說CAP原則,指的是分布式系統中的一致性(Consistency)、可用性(Availability)、分區容錯性(Patitiontolerence),三者不可全得。
- 一致性:指的是分布式所有節點在同一時間的數據完全一致,對于一致性,一致的程度可以分為強、弱、最終一致性:
- 強一致性:對于關系數據庫,要求更新數據能夠被后續的訪問都能看到。如A更新了V0到V1,其他線程后續讀取的時候必須是V1。
- 弱一致性:能夠容忍后續讀取部分或者全部訪問不到。如A更新V0到V1,可以容忍其他線程讀取的時候仍是V0;
- 最終一致性:弱一致性的特例,保證在沒有后續更新的前提下,系統經過一段時間要求返回最近一次更新后的數據。
- 可用性:分布式集群一部分節點故障后,集群整體是否還能響應客戶請求。
- 分區容錯:某節點故障或網絡分區延遲,集群整理仍能對外提供設計好的一致性和可用性的服務。
主流注冊中心對比
特點/注冊服務組件 | Eureka | Zookeeper | Nacos | Cousul |
---|---|---|---|---|
服務健康檢查 | 可配支持 | (弱)長連接,keepalive | 服務狀態、內存、硬盤等 | 連接心跳 |
多數據中心 | 支持 | - | 支持 | 支持 |
kv存儲服務 | - | 支持 | - | 支持 |
一致性算法 | - | paxos | Raft(CP)Distro(AP) | raft |
數據一致性 | AP | CP | AP、CP | CA |
多語言支持 | http(Sidecar模式) | 客戶端 | http(Sidecar模式) | 支持http和DNS |
Watch支持 | 支持long polling/大部分增量 | 支持 | 支持long polling/大部分增量 | 全量/支持long polling |
自身監控 | metrics | - | metrics | metrics |
安全 | - | acl | - | acl/https |
Spring Cloud集成 | 已支持 | 已支持 | 已支持 | 已支持 |
數據模型 | 實例級別 | 無 | 服務-集群-實例 | 實例級別 |
Eureka:是SpringCloud生態核心,通過對Netfiix Eureka的二次封裝提供服務注冊和發現功能。Eureka 與SpringCloud生態深度結合,獲得大量用戶。Eureka集群數據是AP,集群每個節點具有相同地位,最大程度保證集群節點故障,注冊中心的可用性。
Zookeeper:是應用于分布式應用程序的高性能分布式協調服務,它暴露了一組簡單的公共服務(提供java和C接口),如命名、配置管理、集群服務、分布式鎖等,分布式應用程序可以基于此實現更高級別的服務進行同步、組合命名。是RPC框架首選注冊中心。
Nacos:致力于幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。
對于Spring Cloud微服務,目前只要還是在Eureka和Nacos上進行選擇:
- Eureka由于其閉源,基本生產級微服務搭建不要考慮Eureka。
- Nacos目前社區活躍,其在集群擴展上表現優秀。同時其注冊中心、配置中心統一集成,以及其支持命名空間的隔離,使得項目在微服務服務治理和配置集中化管理上大大減小投入,可以說目前Nacos應該是Spring Cloud首選注冊中心。Nacos集成
API網關
為什么需要使用API網關
傳統單體應用,客戶端訪問服務器采用訪問ip+端口+服務接口前綴,客戶端程序需要維護服務實例列表,如果后續系統擴展,對于客戶端開發來說是一個災難。又如目前有些分布式架構采用F5+Nginx等設施的路由和負載,然后轉發到各個不同的服務實例,此模式下需要專業運維人員進行服務實例列表清單和路由規則進行維護,當有服務實例增減和IP地址變更,運維人員需要手工更新路由規則和實例清單信息以保證實例信息和中間配置的一致性。如果系統規模不大的情況,手工維護Nginx路由規則和實例清單不算復雜,如果系統規模達到一定程度,有幾十、上百、上千的服務實例需要維護,那么對于運維人員來說也是極大的挑戰,同時也容易提高配置錯誤的概率。
服務網關是微服務系統唯一入口,采用類似外觀模式封裝了系統內部架構,為客戶端提供定制化API服務,同時提供登錄鑒權、監控、負載均衡、請求分片與管理、靜態響應處理、多協議支持、限流、熔斷等高級功能。服務網關能夠通過框架集成實現自動發現和管理實例,并且提供如驗簽、登錄校驗、監控等通過功能,使得微服務開發更加專注業務邏輯的實現。
目前Spring Cloud 生態,可供我們選擇的網關主要還是Spring Cloud Zuul和Spring Cloud Gateway。
- Spring Cloud Zuul 是集成Netflix Zuul組件,與Spring Cloud有很好的集成,缺點是1.x 異步性能不足。
- Spring Cloud Gateway 是Spring Cloud 生態全新項目,基于Spring 5、Spring Boot 2.X、Project Reactor實現的API網關,旨在為微服務提供簡單高效的API路由管理方法。
Spring Cloud Gateway 作為Spring Cloud 生態中的網關,目標是代替Zuul 1.X。Spring Cloud 2.X版本目前仍未對Zuul 2.X高性能版本進行集成,仍使用的是非Reactor的老版本Zuul網關。
- 目前Spring Cloud dependencies 最新版本Hoxton.SR8 仍使用的是Zuul 1.3.1
- Zuul 2.x 高性能Reactor版本本身與18年5月開源,目前最新版本2.1.9
Spring Cloud Gateway集成