Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

應用架構演進

這裏的架構演進應該是從服務化的角度來講,應該說隨着業務發展,應用規模擴大,系統的一些公共服務就會抽取出來,獨立開發,部署,維護,用來解決併發,擴展,維護的問題。web

傳統垂直架構面試

有的地方也叫單體應用,以mvc模式開發:redis

  1. 全部應用代碼統一打包,代碼全部接口本地api調用,不多存在遠程服務調用;
  2. 單機或主備,應用作集羣部署;
  3. DB主從等。

這種並無什麼很差,發展初期大可能是這樣,體量沒那麼大,也不須要考慮高併發大流量可擴展性什麼的,簡單粗暴,解決業務需求就好,活下去才能活的更好。算法

可是必須明白這種簡單架構存在的一些問題:sql

1. 業務不斷髮展,功能逐漸增多,應用的開發維護成本變高,部署效率下降,隨便改個代碼,編譯一次十幾分鍾就浪費了。悲劇,咱們有個系統纔開發3年,就碰到這種狀況,一次打包編譯部署,13分鐘結束。docker

2. 不一樣的人負責不一樣的部分,一些通用代碼、公共代碼就各寫各的,不能複用,若是隻是util還好,可是一些外部服務的都有重複,那就happy了(不過這種狀況的出現,不必定是架構問題,更多多是管理);編程

3. 不斷地上新需求,不斷地改代碼,有時測試不到位,指定哪裏埋了bug,上生產後系統就down了,牽一髮而動全身;json

4. 可維護性,可靠性,擴展性變差。api

既然有這些問題,就要解決啊,業務就會提要求,你要解決啊,要否則影響我業務發展,影響我ipo上市啊,苦逼的碼農開始幹活了。緩存

不提應用的拆分主從那些手段,但從拆分後應用交互看,原來的本地api交互變成的遠程api的調用,這裏就出現了rpc,固然也有走esb,webservice。其實拆分後挺麻煩的,光一個分佈式事務就能折騰死人。

RPC架構

Remote Procedure Call,遠程方法調用,屏蔽底層實現細節,像調用本地方法同樣調用遠程服務。

上個做者的圖:

Java編程良心推薦——分佈式架構原理解析

這個圖對於大多數rpc框架通用,實現的幾個技術點:

1. 服務提供者發佈服務:服務接口定義,數據結構,服務提供者信息等;

2. 客戶端遠程調用:一般是使用jdk的代碼代理攔截;

3. 底層通訊:如今應該更可能是使用netty吧,固然也有走支持http的;

4. 序列化:關注序列化反序列性能,xml,json,hessiaon,pb,protostuff,kryo等;

做者給了個socket實現簡單demo,來實現遠程調用,說明上面幾個技術點。

經常使用的rpc框架

1. Thrift;

2. Hadoop的Avro-RPC;

3. Hessian;

4. gRPC;

單論rpc的話,沒太多可說的,但是若是加上服務治理,那複雜度就幾何倍數增加了。服務治理裏面東西太多了,動態註冊,動態發現,服務管控,調用鏈分析等等問題這些問題,單憑rpc框架解決不了,因此如今經常使用的說的服務化框架,一般指的是rpc+服務治理2個點。

SOA服務化架構

感受soa架構應該是在rpc以前出現,用來解決異構系統的交互,一般的實現是經過ESB,WSDL來處理。其粒度一般來講是比較粗的。也存在服務治理方面的問題。

微服務

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

1. 原子服務,粒度細;

2. 獨立部署,主要是容器;

分享篇文章:雲棲肥俠的文章 微服務(Microservice)那點事 。

MSA與SOA的對比:

  1. 服務拆分粒度:soa首要解決的是異構系統的服務化,微服務專一服務的拆分,原子服務;
  2. 服務依賴:soa主要處理已有系統,重用已有的資產,存在大量服務間依賴,微服務強調服務自治,原子性,避免依賴耦合的產生;
  3. 服務規模:soa服務粒度大,大多數將多個服務合併打包,所以服務實例數有限,微服務強調自治,服務獨立部署,致使規模膨脹,對服務治理有挑戰;
  4. 架構差別:微服務一般是去中心化的,soa一般是基於ESB的;
  5. 服務治理:微服務的動態治理,實時管控,而soa一般是靜態配置治理;
  6. 交付:微服務的小團隊做戰。

感受在有了docker後,微服務這個概念忽然火了起來,總結就是微服務+容器+DevOps。

Java編程良心推薦——分佈式架構原理解析

分佈式服務框架入門

背景

應用從集中式走向分佈式

隨着業務的發展致使功能的增多,傳統的架構模式開發,測試,部署整個流程變長,效率變低,後臺服務的壓力變大,只能經過硬件擴容來暫時緩解壓力,但解決不了根本性問題:

  1. 應用規模變大,開發維護成本變高,部署效率下降;
  2. 代碼複用:原來是本地api調用,致使一些公用功能多是按需開發,不統一,隨意等問題;
  3. 交付面臨困難:主要是業務變得複雜,新增修改測試變得困難,拉長整個流程。

通用法寶:拆分,大系統拆小系統,獨立擴展和伸縮。

  1. 縱向:分業務模塊;
  2. 橫向:提煉核心功能,公共業務;

須要服務治理

大拆小,核心服務提煉後,服務的數量變多,並且須要一些運行態的管控,這時候就須要服務治理:

  1. 服務生命週期管理;
  2. 服務容量規劃;
  3. 運行期治理;
  4. 服務安全。

服務框架介紹

Dubbo

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

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

HSF

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

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

Coral Service

這個沒據說過,孤陋寡聞了。

Java編程良心推薦——分佈式架構原理解析

框架設計

架構原理

萬變不離其中,這張圖能夠歸納rpc的一些通用原理:

Java編程良心推薦——分佈式架構原理解析

細化了下:

Java編程良心推薦——分佈式架構原理解析

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

功能

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

性能

Java編程良心推薦——分佈式架構原理解析

可靠性

Java編程良心推薦——分佈式架構原理解析

分佈式的,面試會問,用池子的話講就是,知識點啊。

服務治理

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

通信框架

技術點

  1. 長鏈接:主要是鏈路的建立過程到最後的關閉,耗時耗資源;每次調用都要建立的話,調用時延的問題,極可能鏈路建立的耗時比代碼真正執行時長還多;
  2. BIO仍是NIO:主要是線程模型的選擇,推薦篇文章 IO - 同步,異步,阻塞,非阻塞 (亡羊補牢篇);
  3. 自研仍是使用開源NIO框架:通常來講仍是使用開源吧,技術成熟,社區支持,如今netty和mina使用較多了吧。
Java編程良心推薦——分佈式架構原理解析

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

1. 通用性api;

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

可靠性設計

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

鏈路有效性

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

1. tcp層面,即tcp的keep-alive,做用於整個tcp協議棧;

2. 協議層的心跳檢測,主要存在於長鏈接協議中,例如smpp協議;

3. 應用層的心跳,業務雙方的定時發送心跳消息;

第2個沒據說過,經常使用的是1,3。通常使用netty的話用的是netty的讀寫空閒來實現心跳。

斷連

無論由於網絡掛了仍是服務端宕機,仍是心跳超時什麼的,致使鏈路不可用關閉,這時候就須要鏈路重連,須要注意的一點就是短連後,不要當即重連,留時間給系統釋放資源,能夠scheduler處理。

消息緩存重發

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

資源釋放

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

性能設計

性能差的三宗罪

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

1. 通信模型的選擇,主要是阻塞非阻塞那些東西;

2. 序列化反序列化(後面有章單講序列化);

3. 線程模型,主要是服務端選擇什麼樣的線程模型來處理消息。

通訊性能三原則

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

  1. 傳輸:BIONIOAIO的選擇;
  2. 選擇自定義協議棧,便於優化;
  3. 服務端線程模型,單線程處理仍是線程池,線程池是一個,仍是分優先級,Reactor仍是其餘什麼的。

高性能之道這節做者講了netty的優點。

序列化與反序列化

也就是一般所說的編碼、解碼。一般的通信框架會提供編解碼的接口,也會內置一些經常使用的序列化反序列化工具支持。

與通信框架和協議的關係,感受能夠理解爲:通信框架是通道,其上跑的碼流數據是利用各類序列化編碼後的各類協議。

功能設計

各類序列化框架須要考慮的主要有:

  • 序列化框架自己的功能的豐富,支持的數據類型;
  • 多語言的支持;
  • 兼容性,往大了說:
  1. 服務接口的先後兼容;
  2. 協議的兼容;
  3. 支持的數據類型的兼容。
  • 性能,目的是最少的資源,最快的速度,最大的壓縮:
  1. 序列化後碼流大小;
  2. 序列化的速度;
  3. 序列化的資源佔用。

在擴展性這節,做者講了netty的對序列化的一些內置支持,但實際開發中,通常不太會使用這些東西,都會提供序列化反序列接口,自行擴展定義,因此擴展性特重要。

經常使用的序列化,xml,json,hessian,kryo,pb,ps,看需求須要支持那種,具體能夠搜索各序列化的性能和壓縮後大小。

協議棧

這一章最主要的是講了自定義協議棧的設計,已經交互的過程,其餘講的可靠性設計什麼的跟以前通信框架一章有重複。

通訊模型

Java編程良心推薦——分佈式架構原理解析

服務提供者和消費者之間採用單鏈路,長鏈接通訊,鏈路建立流程:

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

2. 服務端校驗:節點ID有效性,重複登陸,ip地址黑白名單等,經過後,返回握手應答信息;

3. 鏈路創建後,客戶端發送業務消息;

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

5. 服務端退出時,關閉鏈接,客戶端感知鏈接關閉,關閉客戶端鏈接。

協議消息定義

Java編程良心推薦——分佈式架構原理解析

Java編程良心推薦——分佈式架構原理解析

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

安全性設計

  1. 內部的,不必定須要認證,也有基於系統,域名,ip的黑白名單,安全認證的;
  2. 外部開發平臺的話,基於祕鑰認證;

服務路由

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

透明化路由

  1. 基於zk的服務註冊中心的發佈訂閱;
  2. 消費者本地緩存服務提供者列表,註冊中心宕機後,不影響已有的使用,只是影響新服務的註冊和老服務的下線。

負載均衡

  • 隨機
  • 輪循
  • 服務調用時延
  • 一致性Hash
  1. 有個一致性hash算法,挺有意思的,redis的客戶端shard用的
Java編程良心推薦——分佈式架構原理解析


  • 黏滯鏈接
  1. 這個應該不太經常使用,服務提供者多數無狀態,一旦有狀態,不利於擴展

這些都是點對點的鏈接,負載均衡大多會在客戶端執行,有種場景會取決於服務端負載,就是服務端服務配置的是域名。

本地路由優先策略

  • injvm:jvm也提供了消費端的服務,能夠改爲優先本jvm,對於消費端來講,不需關注提供者;
  • innative:injvm比較少,多得是多是這種,一個物理機部署多個虛擬機,或者一個容器部署多個服務提供者,消費者不需遠程調用,本機,本地或本機房優先。

路由規則

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

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

- 腳本路由:經過腳本解析實現。

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

路由策略定製

自定義路由場景:

1. 灰度;

2. 引流;

路由策略:

1. 框架提供接口擴展;

2. 配置平臺提供路由腳本配置;

配置化路由

  1. 本地配置:包括服務提供者和消費者,全局配置3種;
  2. 註冊中心:路由策略統一註冊到服務註冊中心,集中化管理;
  3. 動態下發:配置後動態下發各服務消費端。

集羣容錯

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

集羣容錯場景

  • 通訊鏈路故障:
  1. 通訊過程當中,對方宕機致使鏈路中斷;
  2. 解碼失敗等緣由Rest掉連接;
  3. 消費者read-write socketchannel發生IOException致使鏈路中斷;
  4. 網絡閃斷故障;
  5. 交換機異常致使鏈路中斷;
  6. 長時間Full GC致使;
  • 服務端超時:
  1. 服務端沒有及時從網絡讀取客戶端請求消息,致使消息阻塞;
  2. 服務端業務處理超時;
  3. 服務端長時間Full GC;
  • 服務端調用失敗:
  1. 服務端解碼失敗;
  2. 服務端流控;
  3. 服務端隊列積壓;
  4. 訪問權限校驗失敗;
  5. 違反SLA策略;
  6. 其餘系統異常;

業務執行異常不屬於服務端異常。

容錯策略

Java編程良心推薦——分佈式架構原理解析

這圖不錯,關係很清晰。

  • 失敗自動切換(Failover):
  1. 調用失敗後切換鏈路調用;
  2. 服務提供者的防重;
  3. 重試次數和超時時間的設置。
  • 失敗通知(FailBack):失敗後直接返回,由消費端自行處理;
  • 失敗緩存(Failcache):主要是失敗後,緩存重試重發,注意:
  1. 緩存時間、緩存數量;
  2. 緩存淘汰算法;
  3. 定時重試的週期T、重試次數;
  • 快速失敗(Failfast):失敗不處理,記錄日誌分析,可用於大促期間,對非核心業務的容錯。

容錯策略擴展

  1. 容錯接口的開放;
  2. 屏蔽底層細節,用戶自定義;
  3. 支持擴展。

其實還有一點,感受也挺重要,就是支持容錯後本地mcok。調用失敗後的鏈路切換和快速失敗確定要支持,緩存重發能夠不用。

本篇篇幅過長,相信能堅持看到最後的都是對知識求知如渴的人,未來一定不凡。順便點點關注點點讚唄。

歡迎工做一到五年的Java工程師朋友們加入Java架構開發:878249276

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索