一、初識分佈式系統
1、定義
一個分佈式系統是由多個通過網絡互聯的獨立自治的計算節點組成。
這些節點之間基於**消息傳遞機制**進行相互協作,以完成共同的目標。
從用戶的角度看,分佈式系統是一個整體,用戶在使用系統功能的時候,是感覺不到分佈式系統的內部構成和節點之間的協作關係。比如,我們在刷微博時,是感覺不到新浪服務器之間的協作,也更覺不到某一臺服務器的更換,我們只感覺像是在跟一臺服務器交互。
2、幾個要點
-
多個計算節點
計算節點一般指單個計算機,也可以是計算機中的一個進程、線程或者後臺服務。
-
網絡互聯
我們並不關心節點之間是通過有線、無線或者什麼其他網絡通信方式互聯,我們只關心節點之間邏輯上的互聯結構。
-
獨立自治
每個節點都有自己獨立的CPU、獨立的時鐘,發生錯誤的時機和模式也都是相互獨立的。
-
各個節點相互協作以完成共同的目標
-
消息傳遞模型
節點基於消息傳遞模型相互協作,並不是內存共享模型。
如下面的圖所示,節點之間的消息傳遞通常以毫秒計,而如果在單機中,耗時可以納秒計,所以在設計分佈式系統時,應該**儘可能的減少節點之間的通信**,此時通信複雜度是影響系統效率的重要因素。
分佈式系統在設計時,必須要應對局部失效、消息延遲/丟失等錯誤。
虛擬內存管理的作用:
- 擴大物理內存,在內存不夠時,通過這種方法,讓用戶感覺到內存很大;
- 給每個進程提供一個獨立的內存地址空間。
二、分佈式概述
1、背景
爲什麼會出現分佈式系統?
-
大大小小的計算機設備無處不在
-
網絡通信技術高速發展,網絡的規模不斷擴大
-
摩爾定律走到了瓶頸,免費的午餐已經結束
-
越來越多的計算任務需要交由分佈在不同區域的計算節點來協作完成
比如,我們在支付寶上購買電,就涉及到阿里的服務器、國家電網的服務器,如果你的錢在銀行的話,還涉及到銀行的服務器。因此購電的這個任務就需要這多個服務器來協作共同完成。
2、構建分佈式系統的目的
- 提高計算能力——用多臺計算機同時執行任務
- 提高存儲能力——一臺計算機能夠掛載的硬盤是有限的,可以使用多臺計算機
- 提高網絡吞吐能力(併發訪問能力)——一臺計算機的網絡請求是有限的
- 提高可靠性(解決局部失效問題)——主備節點,防止局部失效
- 提高安全性(解決局部攻擊問題)
- 提高可擴展性(解決瓶頸問題)
- 實現資源共享
- 實現跨越時空的協同服務(發揮不同節點的優勢)
3、衡量分佈式系統優劣的特性
-
可擴展性/可伸縮性(Scalability)
- 垂直可擴展性(Vertical Scalability)——把一個單核CPU電腦上的程序複製到一個多核CPU電腦上後,程序的執行效率也會隨之提高
- 水平可擴展性(Horizontal Scalability)——程序的執行效率能夠隨着系統節點的增加而增加
-
容錯性(Fault Tolerance/Reliability)
- 可用性(Availability)——某些節點失效時,系統還能否用
- 可恢復行(Recoverability)——在節點重啓之後,就可以繼續使用
-
透明性(Transparency)——用戶感覺不到分佈式系統的構造
-
開放性(Openness)——
-
安全性(Security)——能夠防止外部/內部攻擊
-
可維護性(Maintainability)——後臺管理員能很方便的管理某個節點
4、設計挑戰例子:數據庫備份
上面的這種一主多備的模式,我們規定當客戶端要寫數據時,只能往主節點上寫,然後主節點把數據更新的消息傳送給其他備份節點,這樣也就保持了各個節點的數據一致性。這種一致性帶來的好處就是客戶端可以從任意的節點讀取數據**,而在現實中讀的數據訪問量也遠遠大於寫的訪問量,就像瀏覽微博時,大部分的時間你都是在看別人的動態,很少發送動態。
採用一主多備模式帶來的好處是:
- 提高了可靠性——在主節點失效後,自動地切換某一個備份節點作爲主節點(這裏就要求分佈式系統各節點的一致性)
- 提高了性能——就像上面說的,客戶端可以從任意的節點上讀取數據。
上面說的,感覺“一主多備”十分的完美,但這樣的模式也還有很多的問題解決,其中一個就是容錯性問題。例如,客戶端請求更新磁盤上的x=2
,這時主節點就開始往其他備份節點上發送消息,但給備份節點2的消息丟失了,如果系統不處理這樣的問題,就破壞了分佈式的一致性。如果想到了用消息確認的方式,那樣就會造成通信複雜度增高。
那怎麼在高效的情況下實現分佈式一致性呢?可以使用Paxos協議
、Raft協議
。
5、分佈式的一致性
分佈式的一致性分爲:
- 嚴格一致性
- 強一致性
- 順序一致性
- 線性一致性
- 弱一致性——像微博下的評論,過五分鐘更新也是可以的,但是像銀行的交易就必須實現強一致性,我現在交易了以後,馬上就要看到金額的變化。
- 最終一致性
6、分佈式系統的例子
- 實現資源共享的分佈式系統(分佈式存儲)
- Web系統、DNS系統
- 網絡文件系統:NFS、HDFS
- P2P資源共享系統:BitTorrent、UTorrent
- 區塊鏈、比特幣
- 高性能計算系統:Map-Reduce、Spark、TensorFlow
- 雲計算
- 網格計算
- 集羣計算
- 分佈式信息系統:跨企業應用系統、金融應用系統
三、分佈式節點之間的通信技術
底層通信技術
- 基於TCP的點對點通信技術
- 基於UDP的點對點通信技術
併發服務技術
上層通信技術
- 遠程過程調用RPC/遠程方法調用RMI
- 基於消息隊列的通信技術
1、遠程過程調用RPC
-
遠程過程調用(Remote Rrocedure Call,RPC):使應用程序可以像調用本地節點上的**過程(子過程)**那樣去調用一個遠程節點上的子程序。
-
對於調用者來說不能區分調用者來自本地還是遠程
-
RPC將面向過程的通用編程模型擴展到了分佈式環境
-
實現了跨進程、跨語言、跨網絡、跨平臺的過程調用
-
強化了面向接口編程的編程風格
A、B計算機規定好調用的接口,就像在Java中,
List
只是接口,ArrayList
、LinkedList
是其實現類。調用者並不用關係內部是怎麼實現的,就需要知道接口的名字就可以直接調用。 -
實現RPC必須要有RPC中間件的支持
RPC一般採用同步調用方式,也就是說調用者在調用遠程服務時,需要等待遠程的服務執行完,才能繼續執行。
2、遠程方法調用RMI
- 遠程方法調用(Remote Method Invocation,RMI):將面向對象的編程模型擴展到了分佈式環境。
- RMI使應用程序可以像調用本機上對象的方法一樣調用遠程主機中對象的方法。
- 利用RMI調用遠程對象的方法時,參數可以是一個本地對象,也可以是另外一個遠程對象(第三個節點)。
- 在整個系統範圍內支持垃圾回收。
- 實現RMI必須要有RMI中間件的支持
3、RPC/RMI中間件的作用
- 定義並利用Socket服務接口實現了一套調用者和被調用者之間的通信協議。例如Java RMI的Java Remote Method Protocol(JRMP)
- 實現了過程參數的序列化、反序列化;過程運算結果的序列化、反序列化。序列化的目的是爲了方便存儲、傳輸,但是在以字節碼的方法保存對象後,在不同的計算機上怎麼過把發序列化成對象。
- 通信過程中的錯誤處理
- 過程服務進程(或遠程對象)的集中註冊與發現(目錄服務)
- 遠程對象的統一標識和生命週期管理,例如,A、B計算機上都有一個
f()
方法,那我們怎麼知道調用的是哪個方法呢? - 在服務端支持併發訪問。(多采用多線程技術),當A、B計算機同時調用C計算機上的
f()
方法時,應該要有兩個線程去執行這個方法。
4、接口定義語言IDL
對於支持跨編程語言調用的RPC/RMI中間件而言,有着一套獨立於任何編程語言的接口定義語言IDL。
爲了將IDL轉化爲本地語言,有了一系列的工具:idl2Java(轉化爲 Java 語言)、idl2CPP(轉化爲 C++ 語言)等。
根據IDL生成stub和skeleton的工具。
//CORBA IDL example
struct Person {
string name;
string place;
long year;
}
interface PersonList {
readonly attribute string listname;
void addPerson(in Person p);
void getPerson(in string name, out Person p);
long number();
}
遠程過程調用的流程:
5、常用的 RPC/RMI 中間件
- Java RMI:Java的自娛自樂
- Microsoft .NET Remoting:.Net的自娛自樂
- CORBA:重量級分佈式對象中間件,跨語言
- gRPC:Google的RPC中間件,高效、開源、跨語言
- Thrift:Facebook、Apache的RPC中間件,高效、開源、跨語言
- Hessian:基於HTTP+二進制,跨語言
- Dubbo:淘寶開源中間件,Java
- Motan:新浪開源中間件,Java
Google Protocol Buffers:一種對象序列化標準和開發庫。
4、Web Service技術
4.1 什麼是Web Service?
-
爲了方便網絡上不同節點之間互操作而定義的一套協議標準,也可視爲實現遠程過程調用的一套協議標準。
-
以 HTTP 作爲傳輸層協議實現 RPC 的一套協議標準。
爲什麼以 HTTP 作爲傳輸層協議?
- 因爲防火牆會對 HTTP 的80端口放行。
- HTTP 的基礎設施較全。
-
方便了 Business to Business 的業務集成。可以將多個第三方服務組織合成一種新的服務。
-
Web系統也不再只是共享文檔,也被用於節點之間的互操作。
-
客服端——服務器模式
-
跨平臺、跨語言、面向接口編程
-
實現面向服務構架(SOA:Service-oriented Architecture)的重要技術之一。
面向服務架構 很類似於面向接口編程——我不管你內部是怎麼實現的,只需要定義好接口給我調用就可以了。而面向服務架構就是 暴露出服務。比如說下面的旅行代理服務,客戶不管你是怎麼訂票的、怎麼訂酒店的。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-obQY7bwV-1586163557327)(images/QQ20200325-131233.png)]
4.2 Web Service主要包含哪些標準協議?
-
消息編碼標準(XML)
-
傳輸協議標準(HTTP\SMTP\TCP\UDP)——>更多的是使用HTTP
-
遠程對象訪問協議(即遠程方法調用協議):SOAP(Simple Object Access Protocol)
-
Web 服務描述語言:WSDL(Web Services Description Language) (主要描述服務接口定義)
類似於上面的 IDL
-
服務目錄、服務註冊、服務發現:UDDI(Universal Discovery Description and Integration)
-
安全相關標準:簽名、加密、認證等
-
服務組合、服務編排
5、僅支持點對點通信的缺點
- 在複雜分佈式系統中,僅支持點對點通信會使不同節點之間的通信關係十分複雜(如上圖:一個生產者必須得建立3個 socket 和3個消費者建立連接),耦合度高。
- 數據生產節點需要記錄多個消費節點的標識,消費節點需要記錄多個生產節點的標識。(如果現在消費者中加入了一個 “異常分析” 節點,那麼3個生產者的節點都需要記錄這個節點的標識)
- 可擴展性差:每增加一個生產者或者消費者會對多個節點產生影響。
- 容錯性差:節點失效後,會丟失數據;生產者、消費者速度不匹配時也會丟失數據(這種速度不匹配只是暫時上的不匹配)。
5.1 解決方案——增加中介節點
-
降低了耦合度:所有的生產者只會向 “中介節點” 發送數據;所有的消費者也只會從 “中介節點” 訂閱自己需要的數據。
-
提高了容錯性:中介節點具有數據緩存功能,部分節點失效、或者通信雙方速度暫時不匹配時數據也不會丟失。
-
提高了可擴展性:增加消費節點對生成節點無影響;增加同類型的生成節點,對消費節點無影響。(在消費節點中增加 “異常處理” 節點後,該節點只需要自己去訂閱自己需要的數據,並不會影響其它節點)(增加生產者節點也是同理)。
-
需要注意,“中介節點” 本身也是分佈式的,所有不用擔心中介節點失效的問題。
6、基於消息中間件的通信技術
- 面向消息中間件(MOM:Message Oriented Middleware)提供了一種分佈式消息隊列服務,使得節點之間可以實現基於消息的形式靈活的
異步通信
。
上面的異步通信是指:
- 發送方可以在任何時刻發出消息,不必等待接收方上線,更不用等消息發送成功後再做下一步工作。
- 接收方不必以阻塞方法等待消息的到來。
7、分佈式系統的總線型架構
- 不同節點之間通過虛擬總線相連。
- 消息發送方不必知道接收方是誰,接收方也不必知道發送方是誰。
- 發送者和接受者之間用異步方法通信。
- 一種松耦合的架構。
- 不同節點完成不同的功能,分工協作
8、MOM 支持的兩種通信技術
- 消息隊列通信模式:
- 在生產者和消費者之間建立的滿足先進先出的消息隊列
- 消息隊列的消息一旦被某個消費者取走,該消息就會從該隊列中刪除。
- 消息的出隊按照某種 負載均衡策略發送給特定的消費者。
- 高級隊列模式:帶優先級的隊列;支持持久性的隊列(可以持久化到硬盤)。
- 主題/訂閱通信模式:
- 支持向一個特定的消息主題發佈消息。
- 多個訂閱同一主題的消費者可以同時接收發到該消息主題的消息。
- 可以靈活實現廣播/組播等多對多通信模式。
上面兩者的本質區別在於 黃底 標識的部分。
9、常用的MOM中間件
ActiveMQ
- 由 Apache 出品,完全兼容 JMS(Java Message Service)——一種標準的API接口,類似於
Map
接口,不同的消息中間件就是HashMap
或者EnumMap
; - 爲多種編程語言提供客戶端API;
- 與生產者、消費者客戶端之間採用 AMQP(Adcanced Message Queuing Protocol)標準化協議進行通信;
- 必須部署
中心服務器
作爲消息路由代理
。中心服務器可由服務器集羣
代替。