做者 | 曉土 阿里巴巴高級工程師前端
姊妹篇閱讀推薦:《雲原生時代,分佈式系統設計必備知識圖譜(內含22個知識點)》git
導讀:本文力求從分佈式基礎理論、架構設計模式、工程應用、部署運維、業界方案這幾大方面,介紹基於 MSA(微服務架構)的分佈式知識體系大綱,從而對 SOA 到 MSA 進化有着立體的認識;從概念上和工具應用上更近一步瞭解微服務分佈式的本質,身臨其境的感覺如何搭建全套微服務架構的過程。github
關注「阿里巴巴雲原生」公衆號,回覆「分佈」,便可下載分佈式系統及其知識體系清晰大圖!redis
隨着移動互聯網的發展和智能終端的普及,計算機系統早就從單機獨立工做過渡到多機器協做,集羣按照分佈式理論構建出龐大複雜的應用服務,在分佈式的基礎上正進行一場雲原生的技術革命,完全打破傳統的開發方式,解放了新一代的生產力。算法
分佈式系統知識體系大圖
關注「阿里巴巴雲原生」公衆號,回覆「分佈」,便可下載分佈式系統及其知識體系清晰大圖!spring
基礎理論
SOA 到 MSA 的進化
SOA 面向服務架構
因爲業務發展到必定程度後,須要對服務進行解耦,進而把一個單一的大系統按邏輯拆分紅不一樣的子系統,經過服務接口來通信。面向服務的設計模式,最終須要總線集成服務,並且大部分時候還共享數據庫,出現單點故障時會致使總線層面的故障,更進一步可能會把數據庫拖垮,因此纔有了更加獨立的設計方案的出現。數據庫
MSA 微服務架構
微服務是真正意義上的獨立服務,從服務入口到數據持久層,邏輯上都是獨立隔離的,無需服務總線來接入,但同時也增長了整個分佈式系統的搭建和管理難度,須要對服務進行編排和管理,因此伴隨着微服務的興起,微服務生態的整套技術棧也須要無縫接入,才能支撐起微服務的治理理念。編程
節點與網絡
節點
傳統的節點也就是一臺單體的物理機,全部的服務都揉進去包括服務和數據庫;隨着虛擬化的發展,單臺物理機每每能夠分紅多臺虛擬機,實現資源利用的最大化,節點的概念也變成單臺虛擬機上面服務;近幾年容器技術逐漸成熟後,服務已經完全容器化,也就是節點只是輕量級的容器服務。整體來講,節點就是能提供單位服務的邏輯計算資源的集合。後端
網絡
分佈式架構的根基就是網絡,無論是局域網仍是公網,沒有網絡就沒法把計算機聯合在一塊兒工做,可是網絡也帶來了一系列的問題。網絡消息的傳播有前後,消息丟失和延遲是常常發生的事情,咱們定義了三種網絡工做模式:設計模式
-
同步網絡
-
半同步網絡
-
異步網絡
- 節點獨立執行
- 消息延遲無上限
- 無全局鎖
- 部分算法不可行
經常使用網絡傳輸層有兩大協議的特色簡介:
-
TCP 協議
- 首先 tcp 協議傳輸可靠,儘管其餘的協議能夠更快傳輸
- tcp 解決重複和亂序問題
-
UDP 協議
時間與順序
時間
慢速物理時空中,時間獨自在流淌着,對於串行的事務來講,很簡單的就是跟着時間的腳步走就能夠,先來後到的發生。然後咱們發明了時鐘來刻畫以往發生的時間點,時鐘讓這個世界井井有理。可是對於分佈式世界來講,跟時間打交道着實是一件痛苦的事情。
分佈式世界裏面,咱們要協調不一樣節點之間的先來後到關係,不一樣節點自己認可的時間又互不相讓,因而咱們創造了網絡時間協議(NTP)試圖來解決不一樣節點之間的標準時間,可是 NTP 自己表現並不盡如人意,因此咱們又構造出了邏輯時鐘,最後改進爲向量時鐘:
-
邏輯時鐘
- 定義事件先來後到
- t' = max(t, t_msg + 1)
順序
有了衡量時間的工具,解決順序問題天然就是水到渠成了。由於整個分佈式的理論基礎就是如何協商不一樣節點的一致性問題,而順序則是一致性理論的基本概念,因此前文咱們才須要花時間介紹衡量時間的刻度和工具。
一致性理論
說到一致性理論,咱們必須看一張關於一致性強弱對系統建設影響的對比圖:
該圖對比了不一樣一致性算法下的事務、性能、錯誤、延遲的平衡。
強一致性 ACID
單機環境下咱們對傳統關係型數據庫有苛刻的要求,因爲存在網絡的延遲和消息丟失,ACID 即是保證事務的原則,這四大原則甚至咱們都不須要解釋出來就耳熟能詳了:
- Atomicity:原子性,一個事務中的全部操做,要麼所有完成,要麼所有不完成,不會結束在中間某個環節;
- Consistency:一致性,在事務開始以前和事務結束之後,數據庫的完整性沒有被破壞;
- Isolation:隔離性,數據庫容許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性能夠防止多個事務併發執行時,因爲交叉執行而致使數據的不一致;
- Durabilit:事務處理結束後,對數據的修改就是永久的,即使系統故障也不會丟失。
分佈式一致性 CAP
分佈式環境下,咱們沒法保證網絡的正常鏈接和信息的傳送,因而發展出了 CAP/FLP/DLS 這三個重要的理論:
- CAP:分佈式計算系統不可能同時確保一致性(Consistency)、可用性(Availablity)和分區容忍性(Partition);
- FLP:在異步環境中,若是節點間的網絡延遲沒有上限,只要有一個惡意的節點存在,就沒有算法能在有限的時間內達成共識;
-
DLS:
- 在一個部分同步網絡的模型(也就是說:網絡延時有界限可是咱們並不知道在哪裏)下運行的協議能夠容忍 1/3 任意(換句話說,拜占庭)錯誤;
- 在一個異步模型中的肯定性的協議(沒有網絡延時上限)不能容錯(不過這個論文沒有提起隨機化算法能夠容忍 1/3 的錯誤);
- 同步模型中的協議(網絡延時能夠保證小於已知 d 時間),能夠使人吃驚的達到 100% 容錯,雖然對 1/2 的節點出錯能夠發生的狀況有所限制。
弱一致性 BASE
多數狀況下,其實咱們也並不是必定要求強一致性,部分業務能夠容忍必定程度的延遲一致,因此爲了兼顧效率,發展出來了最終一致性理論 BASE。BASE 是指基本可用(Basically Available)、軟狀態( Soft State)、最終一致性( Eventual Consistency):
- 基本可用(Basically Available):基本可用是指分佈式系統在出現故障的時候,容許損失部分可用性,即保證核心可用;
- 軟狀態(Soft State):軟狀態是指容許系統存在中間狀態,而該中間狀態不會影響系統總體可用性。分佈式存儲中通常一份數據至少會有三個副本,容許不一樣節點間副本同步的延時就是軟狀態的體現;
- 最終一致性(Eventual Consistency):最終一致性是指系統中的全部數據副本通過必定時間後,最終可以達到一致的狀態。弱一致性和強一致性相反,最終一致性是弱一致性的一種特殊狀況。
一致性算法
分佈式架構的核心就在於一致性的實現和妥協,那麼如何設計一套算法來保證不一樣節點之間的通訊和數據達到無限趨向一致性,就很是重要了。保證不一樣節點在充滿不肯定性網絡環境下能達成相同副本的一致性是很是困難的,業界對該課題也作了大量的研究。
首先咱們要了解一致性的大前提原則 (CALM):
CALM 原則的全稱是 Consistency and Logical Monotonicity ,主要描述的是分佈式系統中單調邏輯與一致性的關係,它的內容以下,參考 consistency as logical monotonicity。
- 在分佈式系統中,單調的邏輯都能保證 「最終一致性」,這個過程當中不須要依賴中心節點的調度;
- 任意分佈式系統,若是全部的非單調邏輯都有中心節點調度,那麼這個分佈式系統就能夠實現最終「一致性」。
而後再關注分佈式系統的數據結構 CRDT(Conflict-Free Replicated Data Types):
咱們瞭解到分佈式一些規律原則以後,就要着手考慮如何來實現解決方案,一致性算法的前提是數據結構,或者說一切算法的根基都是數據結構,設計良好的數據結構加上精妙的算法能夠高效的解決現實的問題。通過前人不斷的探索,咱們得知分佈式系統被普遍採用的數據結構 CRDT。
參考《談談 CRDT》,A comprehensive study of Convergent and Commutative Replicated Data Types
- 基於狀態(state-based):即將各個節點之間的 CRDT 數據直接進行合併,全部節點都能最終合併到同一個狀態,數據合併的順序不會影響到最終的結果;
- 基於操做(operation-based):將每一次對數據的操做通知給其餘節點。只要節點知道了對數據的全部操做(收到操做的順序能夠是任意的),就能合併到同一個狀態。
瞭解數據結構後,咱們須要來關注一下分佈式系統的一些重要的協議HATs(Highly Available Transactions),ZAB(Zookeeper Atomic Broadcast):
參考《高可用事務》,《ZAB 協議分析》
最後要學習的是業界主流的一致性算法 :
說實話具體的算法我也還沒徹底搞懂,一致性算法是分佈式系統最核心本質的內容,這部分的發展也會影響架構的革新,不一樣場景的應用也催生不一樣的算法。
這一節咱們說完分佈式系統裏面核心理論基礎,如何達成不一樣節點之間的數據一致性,下面咱們將會講到目前都有哪些主流的分佈式系統。
場景分類
文件系統
單臺計算機的存儲始終有上限,隨着網絡的出現,多臺計算機協做存儲文件的方案也相繼被提出來。最先的分佈式文件系統其實也稱爲網絡文件系統,第一個文件服務器在 1970 年代被髮展出來。在 1976 年迪吉多公司設計出 File Access Listener(FAL),而現代分佈式文件系統則出自赫赫有名的 Google 的論文,《The Google File System》奠基了分佈式文件系統的基礎。現代主流分佈式文件系統參考《分佈式文件系統對比》,下面列舉幾個經常使用的文件系統:
- HDFS
- FastDFS
- Ceph
- mooseFS
數據庫
數據庫固然也屬於文件系統,主數據增長了事務、檢索、擦除等高級特性,因此複雜度又增長了,既要考慮數據一致性也得保證足夠的性能。傳統關係型數據庫爲了兼顧事務和性能的特性,在分佈式方面的發展有限,非關係型數據庫擺脫了事務的強一致性束縛,達到了最終一致性的效果,從而有了飛躍的發展,NoSql(Not Only Sql) 也產生了多個架構的數據庫類型,包括 KV、列式存儲、文檔類型等。
- 列式存儲:Hbase
- 文檔存儲:Elasticsearch,MongoDB
- KV 類型:Redis
- 關係型:Spanner
計算
分佈式計算系統構建在分佈式存儲的基礎上,充分發揮分佈式系統的數據冗餘災備,多副本高效獲取數據的特性,進而並行計算,把本來須要長時間計算的任務拆分紅多個任務並行處理,從而提升了計算效率。分佈式計算系統在場景上分爲離線計算、實時計算和流式計算。
- 離線:Hadoop
- 實時:Spark
- 流式:Storm,Flink/Blink
緩存
緩存做爲提高性能的利器無處不在,小到 CPU 緩存架構,大到分佈式應用存儲。分佈式緩存系統提供了熱點數據的隨機訪問機制,大大了提高了訪問時間,可是帶來的問題是如何保證數據的一致性,引入分佈式鎖來解決這個問題,主流的分佈式存儲系統基本就是 Redis 了。
消息
分佈式消息隊列系統是消除異步帶來的一系列複雜步驟的一大利器,在多線程高併發場景下,咱們經常須要謹慎設計業務代碼,來保證多線程併發狀況下不出現資源競爭致使的死鎖問題。而消息隊列以一種延遲消費的模式將異步任務都存到隊列,而後再逐個消化。
- Kafka
- RabbitMQ
- RocketMQ
- ActiveMQ
監控
分佈式系統從單機到集羣的形態發展,複雜度也大大提升,因此對整個系統的監控也是必不可少。
應用
分佈式系統的核心模塊就是在應用如何處理業務邏輯,應用直接的調用依賴於特定的協議來通訊,有基於 RPC 協議的,也有基於通用的 HTTP 協議。
日誌
錯誤對應分佈式系統是屢見不鮮,並且咱們設計系統的時候,自己就須要把容錯做爲廣泛存在的現象來考慮。那麼當出現故障的時候,快速恢復和排查故障就顯得很是重要了。分佈式日誌採集存儲和檢索則能夠給咱們提供有力的工具來定位請求鏈路中出現問題的環節。
- 日誌採集:flume
- 日誌存儲:ElasticSearch/Solr,SLS
- 日誌定位:Zipkin
帳本
前文咱們提到所謂分佈式系統,是迫於單機的性能有限,而堆硬件卻又沒法無休止的增長,單機堆硬件最終也會遇到性能增加曲線的瓶頸。因而咱們才採用了多臺計算機來幹一樣的活,可是這樣的分佈式系統始終須要中心化的節點來監控或者調度系統的資源,即便該中心節點也多是多節點組成。區塊鏈則是真正的區中心化分佈式系統,系統裏面只有 P2P 網絡協議各自通訊,沒有真正意義的中心節點,彼此按照區塊鏈節點的算力、權益等機制來協調新區塊的產生。
設計模式
上節咱們列舉了不一樣場景下不一樣分佈式系統架構扮演的角色和實現的功能,本節咱們更進一步概括分佈式系統設計的時候是如何考慮架構設計的、不一樣設計方案直接的區別和側重點、不一樣場景須要選擇合做設計模式,來減小試錯的成本,設計分佈式系統須要考慮如下的問題。
可用性
可用性是系統運行和工做的時間比例,一般以正常運行時間的百分比來衡量。它可能受系統錯誤、基礎架構問題、惡意攻擊和系統負載的影響。分佈式系統一般爲用戶提供服務級別協議(SLA),所以應用程序必須設計爲最大化可用性。
- 健康檢查:系統實現全鏈路功能檢查,外部工具按期經過公開端點訪問系統
- 負載均衡:使用隊列起到削峯做用,做爲請求和服務之間的緩衝區,以平滑間歇性的重負載
- 節流:限制應用級別、租戶或整個服務所消耗資源的範圍
數據管理
數據管理是分佈式系統的關鍵要素,並影響大多數質量的屬性。因爲性能,可擴展性或可用性等緣由,數據一般託管在不一樣位置和多個服務器上,這可能帶來一系列挑戰。例如,必須維護數據一致性,而且一般須要跨不一樣位置同步數據。
- 緩存:根據須要將數據從數據存儲層加載到緩存
- CQRS(Command Query Responsibility Segregation): 命令查詢職責分離
- 事件溯源:僅使用追加方式記錄域中完整的系列事件
- 索引表:在常常查詢引用的字段上建立索引
- 物化視圖:生成一個或多個數據預填充視圖
- 拆分:將數據拆分爲水平的分區或分片
設計與實現
良好的設計包括諸如組件設計和部署的一致性、簡化管理和開發的可維護性、以及容許組件和子系統用於其餘應用程序和其餘方案的可重用性等因素。在設計和實施階段作出的決策對分佈式系統和服務質量和整體擁有成本產生巨大影響。
- 代理:反向代理
- 適配器: 在現代應用程序和遺留系統之間實現適配器層
- 先後端分離: 後端服務提供接口供前端應用程序調用
- 計算資源整合:將多個相關任務或操做合併到一個計算單元中
- 配置分離:將配置信息從應用程序部署包中移出到配置中心
- 網關聚合:使用網關將多個單獨的請求聚合到一個請求中
- 網關卸載:將共享或專用服務功能卸載到網關代理
- 網關路由:使用單個端點將請求路由到多個服務
- 領導人選舉:經過選擇一個實例做爲負責管理其餘實例管理員,協調分佈式系統的雲
- 管道和過濾器:將複雜的任務分解爲一系列能夠重複使用的單獨組件
- 邊車:將應用的監控組件部署到單獨的進程或容器中,以提供隔離和封裝
- 靜態內容託管:將靜態內容部署到 CDN,加速訪問效率
消息
分佈式系統須要一個鏈接組件和服務的消息傳遞中間件,理想狀況是以鬆散耦合的方式,以便最大限度地提升可伸縮性。異步消息傳遞被普遍使用,並提供許多好處,但也帶來了諸如消息排序,冪等性等挑戰
- 競爭消費者:多線程併發消費
- 優先級隊列: 消息隊列分優先級,優先級高的先被消費
管理與監控
分佈式系統在遠程數據中心運行,沒法徹底控制基礎結構,這使管理和監視比單機部署更困難。應用必須公開運行時信息,管理員可使用這些信息來管理和監視系統,以及支持不斷變化的業務需求和自定義,而無需中止或從新部署應用。
性能與擴展
性能表示系統在給定時間間隔內執行任何操做的響應性,而可伸縮性是系統處理負載增長而不影響性能或容易增長可用資源的能力。分佈式系統一般會遇到變化的負載和活動高峯,特別是在多租戶場景中,幾乎是不可能預測的。相反,應用應該可以在限制範圍內擴展以知足需求高峯,並在需求減小時進行擴展。可伸縮性不只涉及計算實例,還涉及其餘元素,如數據存儲、消息隊列等。
彈性
彈性是指系統可以優雅地處理故障並從故障中恢復。分佈式系統一般是多租戶,使用共享平臺服務、競爭資源和帶寬,經過 Internet 進行通訊,以及在商用硬件上運行,意味着出現瞬態和更永久性故障的可能性增長。爲了保持彈性,必須快速有效地檢測故障並進行恢復。
- 隔離:將應用程序的元素隔離到池中,以便在其中一個失敗時,其餘元素將繼續運行
- 斷路器:處理鏈接到遠程服務或資源時可能須要不一樣時間修復的故障
- 補償交易:撤消一系列步驟執行的工做,這些步驟共同定義最終一致的操做
- 健康檢查:系統實現全鏈路功能檢查,外部工具按期經過公開端點訪問系統
- 重試:經過透明地重試先前失敗的操做,使應用程序在嘗試鏈接到服務或網絡資源時處理預期的臨時故障
安全
安全性是系統可以防止在設計使用以外的惡意或意外行爲,並防止泄露或丟失信息。分佈式系統在受信任的本地邊界以外的 Internet 上運行,一般向公衆開放,而且能夠爲不受信任的用戶提供服務。必須以保護應用程序免受惡意攻擊,限制僅容許對已批准用戶的訪問,並保護敏感數據。
- 聯合身份:將身份驗證委派給外部身份提供商
- 看門人: 經過使用專用主機實例來保護應用程序和服務,該實例充當客戶端與應用程序或服務之間的代理,驗證和清理請求,並在它們之間傳遞請求和數據
- 代客鑰匙:使用爲客戶端提供對特定資源或服務的受限直接訪問的令牌或密鑰
工程應用
前文咱們介紹了分佈式系統的核心理論,面臨的一些難題和解決問題的折中思路,羅列了現有主流分佈式系統的分類,並且概括了建設分佈式系統的一些方法論,那麼接下來咱們將從工程角度來介紹真刀真槍搭建分佈式系統包含的內容和步驟。
資源調度
巧婦難爲無米之炊,咱們一切的軟件系統都是構建在硬件服務器的基礎上。從最開始的物理機直接部署軟件系統,到虛擬機的應用,最後到了資源上雲容器化,硬件資源的使用也開始了集約化的管理。本節對比的是傳統運維角色對應的職責範圍,在 devops 環境下,開發運維一體化,咱們要實現的也是資源的靈活高效使用。
過去軟件系統隨着用戶量增長鬚要增長機器資源的話,傳統的方式就是找運維申請機器,而後部署好軟件服務接入集羣,整個過程依賴的是運維人員的人肉經驗,效率低下並且容易出錯。微服務分佈式則無需人肉增長物理機器,在容器化技術的支撐下,咱們只須要申請雲資源,而後執行容器腳本便可。
- 應用擴容:用戶激增須要對服務進行擴展,包括自動化擴容,峯值事後的自動縮容
- 機器下線:對於過期應用,進行應用下線,雲平臺收回容器宿主資源
- 機器置換:對於故障機器,可供置換容器宿主資源,服務自動啓動,無縫切換
網絡管理
有了計算資源後,另外最重要的就是網絡資源了。在現有的雲化背景下,咱們幾乎不會直接接觸到物理的帶寬資源,而是直接由雲平臺統一管理帶寬資源。咱們須要的是對網絡資源的最大化應用和有效的管理。
- 域名申請:應用申請配套域名資源的申請,多套域名映射規則的規範
- 域名變動:域名變動統一平臺管理
- 負載管理:多機應用的訪問策略設定
- 安全外聯:基礎訪問鑑權,攔截非法請求
- 統一接入:提供統一接入的權限申請平臺,提供統一的登陸管理
故障快照
在系統故障的時候咱們第一要務是系統恢復,同時保留案發現場也是很是重要的,資源調度平臺則須要有統一的機制保存好故障現場。
- 現場保留:內存分佈,線程數等資源現象的保存,如 JavaDump 鉤子接入
- 調試接入:採用字節碼技術無需入侵業務代碼,能夠供生產環境現場日誌打點調試
流量調度
在咱們建設好分佈式系統後,最早受到考驗的關口就是網關了,進而咱們須要關注系統流量的狀況,也就是如何對流量的管理,咱們追求的是在系統可容納的流量上限內,把資源留給最優質的流量使用、把非法惡意的流量擋在門外,這樣節省成本的同時確保系統不會被衝擊崩潰。
負載均衡
負載均衡是咱們對服務如何消化流量的通用設計,一般分爲物理層的底層協議分流的硬負載均衡和軟件層的軟負載。負載均衡解決方案已是業界成熟的方案,咱們一般會針對特定業務在不一樣環境進行優化,經常使用有以下的負載均衡解決方案
- 交換機
- F5
- LVS/ALI-LVS
- Nginx/Tengine
- VIPServer/ConfigServer
網關設計
負載均衡首當其衝的就是網關,由於中心化集羣流量最早打到的地方就是網關了,若是網關扛不住壓力的話,那麼整個系統將不可用。
- 高性能:網關設計第一須要考慮的是高性能的流量轉發,網關單節點一般能達到上百萬的併發流量
- 分佈式:出於流量壓力分擔和災備考慮,網關設計一樣須要分佈式
- 業務篩選:網關同設計簡單的規則,排除掉大部分的惡意流量
流量管理
- 請求校驗:請求鑑權能夠把多少非法請求攔截,清洗
- 數據緩存:多數無狀態的請求存在數據熱點,因此採用 CDN 能夠把至關大一部分的流量消費掉
流控控制
剩下的真實流量咱們採用不一樣的算法來分流請求。
服務調度
所謂打鐵還需自身硬,流量作好了調度管理後,剩下的就是服務自身的健壯性了。分佈式系統服務出現故障是常有的事情,甚至咱們須要把故障自己當作是分佈式服務的一部分。
註冊中心
咱們網絡管理一節中介紹了網關,網關是流量的集散地,而註冊中心則是服務的根據地。
- 狀態類型:第一好應用服務的狀態,經過註冊中心就能夠檢測服務是否可用
- 生命週期:應用服務不一樣的狀態組成了應用的生命週期
版本管理
- 集羣版本:集羣不用應用有自身對應的版本號,由不一樣服務組成的集羣也須要定義大的版本號
- 版本回滾:在部署異常的時候能夠根據大的集羣版本進行回滾管理
服務編排
服務編排的定義是:經過消息的交互序列來控制各個部分資源的交互。參與交互的資源都是對等的,沒有集中的控制。微服務環境下服務衆多咱們須要有一個總的協調器來協議服務之間的依賴,調用關係,K8s 則是咱們的不二選擇。
服務控制
前面咱們解決了網絡的健壯性和效率問題,這節介紹的是如何使咱們的服務更加健壯。
-
發現資源管理那節咱們介紹了從雲平臺申請了容器宿主資源後,經過自動化腳本就能夠啓動應用服務,啓動後服務則須要發現註冊中心,而且把自身的服務信息註冊到服務網關,便是網關接入。註冊中心則會監控服務的不一樣狀態,作健康檢查,把不可用的服務歸類標記。
-
降級:當用戶激增的時候,咱們首先是在流量端作手腳,也就是限流。當咱們發現限流後系統響應變慢了,有可能致使更多的問題時,咱們也須要對服務自己作一些操做。服務降級就是把當前不是很核心的功能關閉掉,或者不是很要緊的準確性放寬範圍,過後再作一些人工補救。
-
熔斷:當咱們都作了以上的操做後,仍是以爲不放心,那麼就須要再進一步操心。熔斷是對過載的一種自身保護,猶如咱們開關跳閘同樣。好比當咱們服務不斷對數據庫進行查詢的時候,若是業務問題形成查詢問題,這是數據庫自己須要熔斷來保證不會被應用拖垮,而且訪問友好的信息,告訴服務不要再盲目調用了。
- 閉合狀態
- 半開狀態
- 斷開狀態
- 熔斷工具- Hystrix
-
冪等:咱們知道,一個冪等操做的特色是其任意屢次執行所產生的影響均與一次執行的影響相同。那麼就須要對單次操做賦予一個全局的 id 來作標識,這樣屢次請求後咱們能夠判斷來源於同個客戶端,避免出現髒數據。
數據調度
數據存儲最大的挑戰就是數據冗餘的管理,冗餘多了效率變低並且佔用資源,副本少了起不到災備的做用,咱們一般的作法是把有轉態的請求,經過轉態分離,轉化爲無狀態請求。
狀態轉移
分離狀態至全局存儲,請求轉換爲無狀態流量,好比咱們一般會將登錄信息緩存至全局 redis 中間件,而不須要在多個應用中去冗餘用戶的登錄數據。
分庫分表
數據橫向擴展。
分片分區
多副本冗餘。
自動化運維
咱們從資源申請管理的時候就介紹到 devops 的趨勢,真正作到開發運維一體化則須要不一樣的中間件來配合完成。
配置中心
全局配置中心按環境來區分,統一管理,減小了多處配置的混亂局面。
部署策略
微服務分佈式部署是屢見不鮮,如何讓咱們的服務更好地支撐業務發展,穩健的部署策略是咱們首先須要考慮的,以下的部署策略適合不一樣業務和不一樣的階段。
- 停機部署
- 滾動部署
- 藍綠部署
- 灰度部署
- A/B 測試
做業調度
任務調度是系統必不可少的一個環節,傳統的方式是在 Linux 機器上配置 crond 定時任務或者直接在業務代碼裏面完成調度業務,如今則是成熟的中間件來代替。
應用管理
運維工做中很大一部分時間須要對應用進行重啓,上下線操做,還有日誌清理。
容錯處理
既然咱們知道分佈式系統故障是屢見不鮮,那麼應對故障的方案也是不可或缺的環節。一般咱們有主動和被動的方式來處理:
- 主動是在錯誤出現的時候,咱們試圖再試試幾回,說不定就成功了,成功的話就能夠避免了該次錯誤
- 被動方式是錯誤的事情已經發生了,爲了挽回,咱們只是作時候處理,把負面影響降到最小
重試設計
重試設計的關鍵在於設計好重試的時間和次數,若是超太重試次數,或是一段時間,那麼重試就沒有意義了。開源的項目 spring-retry 能夠很好地實現咱們重試的計劃。
事務補償
事務補償符合咱們最終一致性的理念。補償事務不必定會將系統中的數據返回到原始操做開始時其所處的狀態。 相反,它補償操做失敗前由已成功完成的步驟所執行的工做。補償事務中步驟的順序不必定與原始操做中步驟的順序徹底相反。 例如,一個數據存儲可能比另外一個數據存儲對不一致性更加敏感,於是補償事務中撤銷對此存儲的更改的步驟應該會首先發生。對完成操做所需的每一個資源採用短時間的基於超時的鎖並預先獲取這些資源,這樣有助於增長整體活動成功的可能性。 僅在獲取全部資源後才應執行工做。 鎖過時以前必須完成全部操做。
全棧監控
因爲分佈式系統是由衆多機器共同協做的系統,並且網絡也沒法保證徹底可用,因此咱們須要建設一套對各個環節都能監控的系統,這樣咱們才能從底層到業務各個層面進行監控,出現意外的時候能夠及時修復故障,避免更多的問題出現。
基礎層
基礎層面是對容器資源的監測,包含各個硬件指標的負載狀況
中間件
分佈式系統接入了大量的中間件平臺,中間件自己的健康狀況也須要監控。
應用層
- 性能監控:應用層面的須要對每一個應用服務的實時指標(qps,rt),上下游依賴等進行監控
- 業務監控:除了應用自己的監控程度,業務監控也是保證系統正常的一個環節,經過設計合理的業務規則,對異常的狀況作報警設置
監控鏈路
- zipkin/eagleeye
- sls
- goc
- Alimonitor
故障恢復
當故障已經發生後,咱們第一個要作的就是立刻消除故障,確保系統服務正常可用,這個時候一般作回滾操做。
應用回滾
應用回滾以前須要保存好故障現場,以便排查緣由。
基線回退
應用服務回滾後,代碼基線也須要 revert 到前一版本。
版本回滾
總體回滾須要服務編排,經過大版本號對集羣進行回滾。
性能調優
性能優化是分佈式系統的大專題,涉及的面很是廣,這塊簡直能夠單獨拿出來作一個系列來說,本節就先不展開。自己咱們作服務治理的過程也是在性能的優化過程。
參考《高併發編程知識體系》
分佈式鎖
緩存是解決性能問題的一大利器,理想狀況下,每一個請求不須要額外計算就馬上能獲取到結果時最快。小到 CPU 的三級緩存,大到分佈式緩存,緩存無處不在,分佈式緩存須要解決的就是數據的一致性,這個時候咱們引入了分佈式鎖的概念,如何處理分佈式鎖的問題將決定咱們獲取緩存數據的效率。
高併發
多線程編程模式提高了系統的吞吐量,但也同時帶來了業務的複雜度。
異步
事件驅動的異步編程是一種新的編程模式,摒棄了多線程的複雜業務處理問題,同時可以提高系統的響應效率。
總結
最後總結一下,若是有可能的話,請嘗試使用單節點方式而不是分佈式系統。分佈式系統伴隨着一些失敗的操做,爲了處理災難性故障,咱們使用備份;爲了提升可靠性,咱們引入了冗餘。
分佈式系統本質就是一堆機器的協同,而咱們要作的就是搞出各類手段來然機器的運行達到預期。這麼複雜的系統,須要瞭解各個環節、各個中間件的接入,是一個很是大的工程。慶幸的是,在微服務背景下,多數基礎性的工做已經有人幫咱們實現了。前文所描述的分佈式架構,在工程實現了是須要用到分佈式三件套 (Docker+K8S+Srping Cloud) 基本就能夠構建出來了。
分佈式架構核心技術分佈圖以下:
原圖來源:https://dzone.com/articles/deploying-microservices-spring-cloud-vs-kubernetes
分佈式技術棧使用中間件:
原圖來源:https://dzone.com/articles/deploying-microservices-spring-cloud-vs-kubernetes