分布式框架原理


一 傳統垂直mvc項目

1.垂直架構圖

 

通常mvc並不包括數據訪問層,運行也比較簡單,直接運行在一個tomcat等web容器中即可,適合小型項目

垂直架構的缺點

隨着業務的不斷發展,應用規模越來越大,問題越來越凸顯,比如:

1)復雜應用的開發維護成本變高,部署效率逐漸降低,一個功能出問題,整個系統就得重新打包2)團隊協作效率變差,公共功能重復開發,代碼重復率太高3)系統可靠性變差,流量,負載均衡,數據庫壓力變大,因為在一個進程中,如果出現內存溢出等故障,將導致整個節點崩潰,然后集群中的其它節點也會如此4)維護和定制困難,無法隨時拆分,修改一處,牽一發動全身5)新功能上線周期變長,因為公共功能的變更導致測試工作量激增,因為重復代碼多,一個地方修改需要同時修改多個地方,然后修改后繼續測試新功能無法獨立打包測試,需要和整個系統進行一起打包測試,出現bug會導致整個系統重新部署,強耦合導致效率低下

二 RPC架構

RPC(Remote Procedure Call Protocol)——遠程過程調用協議,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通信程序之間攜帶信息數據。在OSI網絡通信模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分布式多程序在內的應用程序更加容易RPC采用客戶機/服務器模式。請求程序就是一個客戶機,而服務提供程序就是一個服務器。首先,客戶機調用進程發送一個有進程參數的調用信息到服務進程,然后等待應答信息。在服務器端,進程保持睡眠狀態直到調用信息到達為止。當一個調用信息到達,服務器獲得進程參數,計算結果,發送答復信息,然后等待下一個調用信息,最后,客戶端調用進程接收答復信息,獲得進程結果,然后調用執行繼續進行。

 

1 RPC架構分為三部分:

服務提供者,運行在服務器端,提供服務接口定義與服務實現類。

服務中心,運行在服務器端,負責將本地服務發布成遠程服務,管理遠程服務,提供給服務消費者使用。

服務消費者,運行在客戶端,通過遠程代理對象調用遠程服務

 

2 RPC框架的核心技術點

1)遠程服務提供者需要以某種形式提供服務的調用相關信息,包括但是不限於服務接口定義,數據結構,或者中間態的服務定義文件服務調用者需要通過一定的途徑獲取遠程服務的調用相關信息,例如接口的定義jar包等2) 遠程代理對象:服務調用者調用的服務實際是遠程服務的本地代理,對於java而言,他的實現就是jdk動態代理,通過動態代理攔截機制,將本地調用封裝成遠程服務調用3)通信:RPC框架與具體的協議無關,只要雙方遵從約定好的即可,比如可以是http invoke,可以是rmi invoke,也可以是其他任意的二進制壓縮協議4)序列化:遠程通信,需要將對象轉換成二進制數據進行網絡傳說,不同的所以需要將數據序列化,不同的序列化框架支持的數據類型,數據包大小,異常類型或者性能都不同不同的RPC框架針對的場景不同,因此技術選擇也各不相同,一些框架支持多種序列化框架,甚至支持用戶自定義序列化框架

3 RPC框架的問題

在大規模服務化之前,應用可能只通過RPC框架 簡單的暴露和引用遠程服務,通過配置的url地址進行遠程調用,路由通過F5硬件負載均衡進行簡單的負載均衡當服務越來越多,服務的url越來越多,管理越來越困難,負載均衡單點壓力變大,此時需要一個服務的注冊中心,動態的注冊和發現服務,使服務位置透明,消費者在本地緩存服務提供者列表,實現軟負載均衡,可以降低對F5硬件負載的依賴,降低硬件成本隨着業務的發展,服務間的依賴關系變的錯綜復雜,甚至分不清哪個應用需要在哪個應用之前啟動,需要一個分布式消息跟蹤系統可視化戰士服務調用鏈,用於以來分析,業務調用路徑梳理,防止服務架構腐化服務的調用量越來越大,服務的容量問題就出現了,某個服務需要多少機器支撐,什么時候該加機器服務上線容易下線難,上線的審批,下線的通知,需要統一的服務生命周期管理流程進行管控,不同的服務安全權限不同,如何保證敏感數據服務不被誤用,服務的訪問安全策略如何定制服務化后隨之而來的就是服務治理問題,純粹的RPC框架服務治理能力都不強悍,需要通過服務框架+服務治理來完成

4常用的rpc框架

Thrift;

Hadoop的Avro-RPC;

Hessian;

gRPC;

單論rpc的話,沒太多可說的,可是如果加上服務治理,那復雜度就幾何倍數增長了。服務治理里面東西太多了,動態注冊,動態發現,服務管控,調用鏈分析等等問題這些問題,單憑rpc框架解決不了,所以現在常用的說的服務化框架,通常指的是rpc+服務治理2個點。

SOA 服務化架構

微服務

MSA也是一種服務化架構風格,正流行ing,服務划分

原子服務,粒度細;

獨立部署,主要是容器;

MSA與SOA的對比:

服務拆分粒度:soa首要解決的是異構系統的服務化,微服務專注服務的拆分,原子服務;服務依賴:soa主要處理已有系統,重用已有的資產,存在大量服務間依賴,微服務強調服務自治,原子性,避免依賴耦合的產生;服務規模:soa服務粒度大,大多數將多個服務合並打包,因此服務實例數有限,微服務強調自治,服務獨立部署,導致規模膨脹,對服務治理有挑戰;架構差異:微服務通常是去中心化的,soa通常是基於ESB的;服務治理:微服務的動態治理,實時管控,而soa通常是靜態配置治理;交付:微服務的小團隊作戰。感覺在有了docker后,微服務這個概念突然火了起來,總結就是微服務+容器+DevOps。

 

第一章架構演進

分布式服務框架入門

背景

應用從集中式走向分布式

隨着業務的發展導致功能的增多,傳統的架構模式開發,測試,部署整個流程變長,效率變低,后台服務的壓力變大,只能通過硬件擴容來暫時緩解壓力,但解決不了根本性問題:應用規模變大,開發維護成本變高,部署效率降低;代碼復用:原來是本地api調用,導致一些公用功能可能是按需開發,不統一,隨意等問題;交付面臨困難:主要是業務變得復雜,新增修改測試變得困難,拉長整個流程。通用法寶:拆分,大系統拆小系統,獨立擴展和伸縮。縱向:分業務模塊;橫向:提煉核心功能,公共業務;需要服務治理大拆小,核心服務提煉后,服務的數量變多,而且需要一些運行態的管控,這時候就需要服務治理:服務生命周期管理;服務容量規划;運行期治理;服務安全。服務框架介紹

Dubbo

阿里開源的Dubbo應該是業界分布式服務框架最出名的了吧,看過公司的rpc框架,Dubbo的擴展性比我們的好的多了,我們的框架每次升級,改動都很多,改天要看下Dubbo的源碼了解了解擴展性。Dubbo架構圖

 Dubbo服務治理 

HSF

淘寶的體量決定了他對極致性能的追求,HSF跨機房特性挺牛。

HSF架構圖

 

HSF服務治理

 Coral Service

 

 

框架設計

架構原理

萬變不離其中,這張圖可以概括rpc的一些通用原理:

 細化了下: 

1 rpc層:底層的通訊框架,通訊協議,序列化和反序列化;2 服務發布訂閱;3 服務治理;

功能

  

性能

 

可靠性

 

服務治理

 

通訊框架

緩存重發可以不用

功能

  

性能

 

可靠性

 

服務治理

 

通訊框架

技術點

長連接:主要是鏈路的創建過程到最后的關閉,耗時耗資源;每次調用都要創建的話,調用時延的問題,很可能鏈路創建的耗時比代碼真正執行時長還多;

BIO還是NIO:主要是線程模型的選擇,推薦篇文章 IO - 同步,異步,阻塞,非阻塞 (亡羊補牢篇);

自研還是使用開源NIO框架:一般來說還是使用開源吧,技術成熟,社區支持,現在netty和mina使用較多了吧。

 

在功能設計方面,作者基於netty給了demo服務端和客戶端的代碼,個人理解:

通用性api;

擴展性,封裝底層,提供上層接口,隔離協議和底層通訊;

可靠性設計

談分布式系統必談可靠性。

鏈路有效性

通過心跳來確認雙方c、s存活,保證鏈路可用,心跳檢測機制分為3個層面:

1. tcp層面,即tcp的keep-alive,作用於整個tcp協議棧; 2. 協議層的心跳檢測,主要存在於長連接協議中,例如smpp協議; 3. 應用層的心跳,業務雙方的定時發送心跳消息;

第2個沒聽說過,常用的是1,3。一般使用netty的話用的是netty的讀寫空閑來實現心跳。

斷連

不管因為網絡掛了還是服務端宕機,還是心跳超時什么的,導致鏈路不可用關閉,這時候就需要鏈路重連,需要注意的一點就是短連后,不要立即重連,留時間給系統釋放資源,可以scheduler處理。

消息緩存重發

底層消息不會立即發送(也會導致半包粘包),斷鏈后,導致消息丟失,看有無業務需求,有就支持斷鏈后消息重發。

資源釋放

主要是斷鏈后,一定要保證資源銷毀和釋放,當然也包括一些線程池,內存等的釋放。

性能設計

性能差的三宗罪

對於底層通訊框架來說,主要是下面幾個:

1. 通訊模型的選擇,主要是阻塞非阻塞那些東西; 2. 序列化反序列化(后面有章單講序列化); 3. 線程模型,主要是服務端選擇什么樣的線程模型來處理消息。

通信性能三原則

既然有上面的3個問題,那就針對這些做優化了:

傳輸:BIO\NIO\AIO的選擇;

選擇自定義協議棧,便於優化;

服務端線程模型,單線程處理還是線程池,線程池是一個,還是分優先級,Reactor還是其他什么的。 高性能之道這節作者講了netty的優勢。

序列化與反序列化

也就是通常所說的編碼、解碼。通常的通訊框架會提供編解碼的接口,也會內置一些常用的序列化反序列化工具支持。 與通訊框架和協議的關系,感覺可以理解為:通訊框架是通道,其上跑的碼流數據是利用各種序列化編碼后的各種協議。

功能設計

各種序列化框架需要考慮的主要有:

序列化框架本身的功能的豐富,支持的數據類型;

多語言的支持;

兼容性,往大了說:

服務接口的前后兼容;

協議的兼容;

支持的數據類型的兼容。

性能,目的是最少的資源,最快的速度,最大的壓縮:

序列化后碼流大小;

序列化的速度;

序列化的資源占用。

實際開發中,一般不太會使用這些東西,都會提供序列化反序列接口,自行擴展定義,所以擴展性特重要。 常用的序列化,xml,json,hessian,kryo,pb,ps,看需求需要支持那種,具體可以搜索各序列化的性能和壓縮后大小。

協議棧

這一章最主要的是講了自定義協議棧的設計,以及交互的過程,其他講的可靠性設計什么的跟之前通訊框架一章有重復。

通信模型

 

服務提供者和消費者之間采用單鏈路,長連接通信,鏈路創建流程:

客戶端發送握手請求,攜帶節點ID等認證信息;

服務端校驗:節點ID有效性,重復登錄,ip地址黑白名單等,通過后,返回握手應答信息;

鏈路建立后,客戶端發送業務消息;

客戶端服務端心跳維持鏈路;

服務端退出時,關閉連接,客戶端感知連接關閉,關閉客戶端連接。

協議消息定義

 

 

通過attachment兼容了擴展性。作者還講了將消息頭的通用序列化和消息體的自定義序列化,看需求吧,我們公司的框架沒做這部分支持,做了簡化,將消息頭和消息體統一封裝,然后再加一個序列化方式組成一條消息發送。

安全性設計

內部的,不一定需要認證,也有基於系統,域名,ip的黑白名單,安全認證的;

外部開發平台的話,基於秘鑰認證;

服務路由

服務路由指的是服務提供者集群部署,消費端如何從服務列表中選擇合適的服務提供者提供服務進行調用。

透明化路由

基於zk的服務注冊中心的發布訂閱;

消費者本地緩存服務提供者列表,注冊中心宕機后,不影響已有的使用,只是影響新服務的注冊和老服務的下線。

負載均衡

隨機

輪循

服務調用時延

一致性Hash

有個一致性hash算法,挺有意思的,redis的客戶端shard用的

 

黏滯連接

這個應該不太常用,服務提供者多數無狀態,一旦有狀態,不利於擴展 這些都是點對點的連接,負載均衡大多會在客戶端執行,有種場景會取決於服務端負載,就是服務端服務配置的是域名。

本地路由優先策略

injvm:jvm也提供了消費端的服務,可以改成優先本jvm,對於消費端來說,不需關注提供者;

innative:injvm比較少,多得是可能是這種,一個物理機部署多個虛擬機,或者一個容器部署多個服務提供者,消費者不需遠程調用,本機,本地或本機房優先。

路由規則

除了上面提供的各種路由負載均衡,還容許自定義路由規則:

條件路由:主要是通過條件表達式來實現;

腳本路由:通過腳本解析實現。

其實應該還有一種客戶端通過代碼自定義路由選擇。這些主要是為了擴展性。

路由策略定制

自定義路由場景:

灰度;

引流;

路由策略:

框架提供接口擴展;

配置平台提供路由腳本配置;

配置化路由

本地配置:包括服務提供者和消費者,全局配置3種;

注冊中心:路由策略統一注冊到服務注冊中心,集中化管理;

動態下發:配置后動態下發各服務消費端。

集群容錯

指的是服務調用失敗后,根據容錯策略進行自動容錯處理。

集群容錯場景

通信鏈路故障:

通信過程中,對方宕機導致鏈路中斷;

解碼失敗等原因Rest掉鏈接;

消費者read-write socketchannel發生IOException導致鏈路中斷;

網絡閃斷故障;

交換機異常導致鏈路中斷;

長時間Full GC導致;

服務端超時:

服務端沒有及時從網絡讀取客戶端請求消息,導致消息阻塞;

服務端業務處理超時;

服務端長時間Full GC;

服務端調用失敗:

服務端解碼失敗;

服務端流控;

服務端隊列積壓;

訪問權限校驗失敗;

違反SLA策略;

其他系統異常; 業務執行異常不屬於服務端異常。

容錯策略

 

失敗自動切換(Failover):

調用失敗后切換鏈路調用;

服務提供者的防重;

重試次數和超時時間的設置。

失敗通知(FailBack):失敗后直接返回,由消費端自行處理;

失敗緩存(Failcache):主要是失敗后,緩存重試重發,注意:

緩存時間、緩存數量;

緩存淘汰算法;

定時重試的周期T、重試次數;

快速失敗(Failfast):失敗不處理,記錄日志分析,可用於大促期間,對非核心業務的容錯。

容錯策略擴展

容錯接口的開放;

屏蔽底層細節,用戶自定義;

支持擴展。 其實還有一點,感覺也挺重要,就是支持容錯后本地mcok。調用失敗后的鏈路切換和快速失敗肯定要支持,緩存重發可以不用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM