【分佈式服務架構原理、設計與實戰】讀書筆記 (一)分佈式微服務架構設計原理

1.1 從傳統單體架構到服務化架構

1.1.1 JEE 架構

JEE 將企業級軟件架構分爲三個層級:算法

  • Web 層:負責與用戶交互或者對外提供接口。
  • 業務邏輯層:爲實現業務邏輯而設計的流程處理和計算處理模塊。
  • 數據存取層:將業務邏輯層處理的結果持久化以待後續查詢,並維護領域模型中對象的生命週期。

JEE 平臺將不一樣的模塊化組件聚合後運行在通用的應用服務器上,例如:WebLogic、WebSphere、JBoss、Tomcat數據庫

圖1-1 JEE 時代的典型架構
clipboard.pngsegmentfault

1.1.2 SSH 架構

  • Struts、Spring、Hibernate
  • 視圖、模型、控制器(Struts MVC)

圖1-3 MVC 模型
clipboard.png後端

圖1-4 SSH 時代的架構
clipboard.png安全

1.1.3 服務化架構

從 JEE 到 SSH ,服務的特色仍然是單體化、服務的粒度抽象爲模塊化組件,全部組件耦合在一個項目中,並配置和運行在一個 JVM 進程中。
爲解決上述問題,SOA 出現了服務器

  • SOA 表明面向服務的架構,俗稱服務化。
  • SOA 將應用程序的模塊化組件經過【定義明確的接口和契約】聯繫起來,接口採用中立的方式進行定義,獨立於某種語言、硬件和操做系統。
  • SOA 一般經過網絡通訊來完成,但不侷限於某種網絡協議,能夠是底層的 TCP/IP,也能夠是應用層的 HTTP,也能夠是消息隊列協議,甚至能夠是約定的某種數據庫存儲形式。

SOA 服務化的發展網絡

1、Web Service
SOA 服務化的一種實現方式,使得運行在不一樣機器及操做系統上的服務互相發現和調用成爲可能,並能夠經過某種協議交換數據。
圖1-5 Web Service 的工做原理圖
clipboard.png架構

  • 服務提供者 Web Service 2 和 Web Service 3 經過 UDDI 協議將服務註冊到 Web Service 目錄服務中。
  • 服務消費者 Web Service 1 經過 UDDI 協議從 Web Service 目錄中查詢服務,並得到服務的 WSDL 服務描述文件。
  • 服務消費者 Web Service 1 經過 WSDL 語言遠程調用和消費 Web Service 2 和 Web Service 3 提供的服務。

2、ESB
ESB 是企業服務總線的簡稱,用戶設計和實現網絡化服務交互和通訊的軟件模型,是 SOA 的另一種實現方式,主要用於企業信息化系統的集成服務場景中。
ESB 也適用於事件處理、數據轉換、映射、消息和事件異步隊列順序處理、安全和異常處理、協議轉換、保證通訊服務的質量等場景。
圖1-6 ESB 架構圖
clipboard.png
ESB 服務密友中心化的服務節點,每一個服務提供者都是經過總線的模式插入系統,總線根據流程的編排負責將服務的輸出進行轉換併發送給流程要求的下一個服務進行處理。併發

ESB 的核心在於企業服務總線的功能和職責負載均衡

  • 監控和控制服務之間的消息路由。
  • 控制可拔插的服務化的功能和版本。
  • 解析服務之間交互和通訊的內容和格式。
  • 經過組合服務、資源和消息處理器來統一編排業務須要的信息處理流程。
  • 使用冗餘來提供服務的備份能力。

1.2 從服務化到微服務

圖1-7 微服務架構
clipboard.png

1.3 微服務架構的核心要點和實現原理

1.3.1 微服務架構中職能團隊劃分

【康威定律】

1.3.2 微服務的去中心化治理

1.3.3 微服務的交互模式

一、讀者容錯模式(Tolerant Reader)

微服務中服務提供者和消費者之間如何對接口的改變進行容錯。

在服務消費者處理服務提供者返回的消息過程當中,須要對服務返回的消息進行過濾,提取本身須要的內容,對多餘或位置內容拋棄,不是硬生生的拋錯。

推薦寬鬆的校驗策略,只有沒法識別信息,繼續處理流程時,才能拋錯。

二、消費者驅動契約模式

消費者驅動契約模式用來定義服務化中服務之間交互接口改變的最佳規則。
服務契約分爲:提供者契約、消費者契約、消費者驅動契約,它從指望與約束的角度描述了服務提供者與消費者之間的聯動關係。

  • 提供者契約:以提供者爲中心,消費者無條件遵照
  • 消費者契約:對某個消費者的需求進行更爲精確的描述,能夠用來標識現有的提供者契約,也能夠用來發現一個還沒有明確的提供者契約。
  • 消費者驅動的契約:表明服務提供者向其全部當前消費者承諾遵照的約束。一旦各消費者把具體的指望告知提供者,則提供者不管在什麼時間和場景下,都不該該打破契約。

圖1-10 服務之間的交互須要使用的三種服務契約
clipboard.png

三、去數據共享模式

1.3.4 微服務的分解和組合模式

一、服務代理模式

根據業務的需求選擇調用後端的某個服務,在返回給使用端前,能夠對後端服務的輸出進行加工,也能夠直接把後端服務的返回結果返回給使用端。
圖1-12 服務代理模式
clipboard.png

【典型案例:平滑的系統遷移】

  1. 在新老系統上雙寫。
  2. 遷移雙寫以前的歷史遺留數據。
  3. 將讀請求切換到新系統『服務代理模式』
  4. 下調雙寫邏輯,只寫新系統。

第 3 步,通常只會對讀請求切換設計一個開關,開關打開時查詢新系統,開關關閉時查詢老系統。

圖1-13 遷移案例中開關的邏輯
clipboard.png

二、聚合服務模式模式

最經常使用的服務組合模式,根據業務流程處理的須要,以必定的順序調用依賴的多個微服務,對依賴的微服務返回的數據進行組合、加工和轉換,返回給使用方。
圖1-14 服務聚合模式的架構
clipboard.png

三、服務串聯模式

相似工做流,最前面的服務1負責接收請求和相應使用方,串聯服務後再與服務1交互,隨後服務 1與服務2交互,最後,從服務2產生的結果通過服務1和串聯服務逐個處理後返回給使用方。

圖1-17 服務串聯模式的架構
clipboard.png

● 使用 RESTful 風格的遠程調用實現;
● 採用同步調用模式,在串聯服務沒有完成返回以前,全部服務都會阻塞和等待;
● 一個請求會佔用一個線程來處理;
● 不建議層級太多,若是能用服務聚合模式,優先使用服務聚合模式;
● 串聯鏈路上增長節點,只要不是在正後方,串聯服務無感知

圖1-18 在串聯服務中調用鏈的最後增長無感知的架構
clipboard.png

圖1-19 服務串聯模式案例的架構圖
clipboard.png

四、服務分支模式

● 服務分支模式是服務代理模式、服務聚合模式和服務串聯模式相結合的產物。
● 分支服務能夠擁有本身的存儲,調用多個後端的服務或者服務串聯鏈,而後將結果進行組合處理再返回給客戶端。
● 分支服務也可使用代理模式,簡單地調用後端的某個服務或者服務鏈,而後將返回的數值直接返回給使用方。

圖1-20 服務分支模式的架構圖
clipboard.png

調用鏈上有多個層次重複調用某基礎服務,致使基礎服務掛掉時影響的流量有累加效果:
假設基礎服務資源池中的機器個數爲 i,一次掛掉的機器個數爲 j,一個調用鏈中調用 x 次基礎服務,那麼正確處理的流量的計算公式爲:

成功率 =  ((i-j) / i) x方

分支模式放大了服務的依賴關係,在現實設計中儘可能保持服務調用級別的簡單,在使用服務組合和服務代理模式時,不要使用服務串聯模式和服務分支模式,以保持服務依賴關係的清晰明瞭。

五、服務異步消息模式

核心的系統服務使用同步調用,核心鏈路之外的服務可使用異步消息隊列進行異步化。

圖1-20 服務異步消息模式的架構
clipboard.png

五、服務共享數據模式

實際上是反模式

圖1-25 服務共享數據模式
clipboard.png

【在下面兩種場景中,仍然須要數據共享模式】:

1、單元化架構

對性能要求高。
圖1-26 單元化架構的示意圖
clipboard.png

2、遺留的總體服務

在重構微服務的過程當中,發現單體服務依賴的數據庫表耦合在一塊兒,對其拆分須要進行反規範化的處理,可能形成數據一致性問題。

1.3.4 微服務的容錯模式

一、艙壁隔離模式
1)微服務容器分組
將微服務的每一個節點服務池分爲三組:

  • 準生產環境;
  • 灰度環境;
  • 生產環境。

圖1-27 服務分組
clipboard.png

2)線程池隔離
圖1-28 線程池隔離
clipboard.png

二、熔斷模式

  • 用電路保險開關來好比熔斷模式。
  • 對微服務系統,當服務的輸入負載迅速增長,若是沒有有效的措施對負載進行熔斷,則會使服務迅速壓垮。

圖1-29 熔斷模式
clipboard.png

三、限流模式
【有以下幾種主流的方法實現限流】:
1)計數器

2)令牌桶
圖1-32 令牌桶結構
clipboard.png

3)信號量

相似於生活中的漏洞
示例:
public class SemaphoreExample {
    private ExecutorService exec = Executors.newCachedThreadPool();
        public static void main(String[] args) {
            final Semaphore sem = new Semaphore(5);
            for (int index = 0; index < 20;  index++) {
                Runnable run = new Runnable() {
                    public void run() {
                    try {
                        // 得到許可
                        sem.acquire();
                        // 同時只有 5 個請求能夠到達這裏
                        Thread.sleep((long) (Math.random()));
                        // 釋放許可
                        sem.release()
                        System.out.println("剩餘許可:" + sem.availablePermits());
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            exec.execute(run);
        }
        exec.shutdown();
    }
}

四、實現轉移模式
【若是微服務架構發生了熔斷和限流,則該如何處理被拒絕的請求】

  • 採用【快速失敗】,直接返回使用方錯誤
  • 是否有【備份】,若是有,則迅速切換到備份服務
  • 【failover策略】,採用重試的方法來解決,這種方法要求服務提供者的服務實現冪等性

1.4 Java 平臺微服務架構的項目組織形式

1.4.1 微服務項目的依賴關係

在微服務領域,jar 包被分爲:

  • 一方庫:本服務在 JVM 進程內依賴的 Jar 包。
  • 二房庫:在服務外經過網絡通訊或 RPC 調用的服務的 Jar 包。
  • 三方庫:所依賴的其餘公司或者組織提

1.4.2 微服務項目的層級結構

Java 微服務項目通常分爲:服務導出層、接口層、邏輯實現層
clipboard.png

  • 服務導出層 : 最後會打包成一個 War 包,包含服務的實現 Jar 包、接口 Jar 包,以及 Web 項目導出 RPC 服務所需的配置文件等。
  • 服務接口層 : 包含業務接口、依賴的 DTO 及須要的枚舉類等,最後打包成 Jar 包,發佈到 Maven 服務器,也包含在服務導出層的 War 包中。
  • 服務實現層 : 包含業務邏輯實現類、依賴的第三方服務的包裝類,以及下層數據庫訪問的 DAO 類,最後打包成 Jar。

【服務實現層的架構圖】
clipboard.png

【服務實現層的反模式架構圖】
clipboard.png

1.4.3 微服務項目的持續發佈

微服務項目須要實現自動化的CI/CD,包括:

  • 代碼管理
  • 自動編譯
  • 發佈 OA
  • 自動化測試
  • 性能測試
  • 準生產部署和測試
  • 生成環境發佈

1.5 服務化管理和治理框架的技術選型

1.5.1 RPC

一、JDK RMI

Java 到 Java 的分佈式調用框架,一個 Java 進程內的服務能夠調用其餘 Java 進程內的服務,使用 JDK 內置的序列化和反序列化協議。

  • 序列化協議:JDK自帶的專用序列化協議,不能跨語言
  • 網絡傳輸協議:底層網絡協議

二、Hessian & Burlap

  • 序列化協議:Hessian 序列化爲二進制協議;Burlap 序列化爲 XML 數據
  • 網絡傳輸協議:HTTP 協議

三、Spring HTTP Invoker

  • 序列化協議:Hessian 序列化爲二進制協議;Burlap 序列化爲 XML 數據
  • 網絡傳輸協議:HTTP 協議

1.5.2

一、Dubbo

  • 提供高性能、透明化的 RPC 遠程服務調用,還提供了基本的服務監控、服務質量和服務調度
  • 支持多種序列化協議和通訊編碼協議,默認使用 Dubbo 協議傳輸 Hessian 序列化的數據
  • 使用 ZooKeeper 做爲註冊中心來註冊和發現服務
  • 經過客戶端負載均衡來路由請求,負載均衡算法包括:隨機、輪詢、最少活躍調用數、一致性哈希等。

二、HSF

High Speed Framework

三、Thrift

  • 採用中間的接口描述語言定義並建立服務
  • 支持跨語言服務開發和調用,幷包含中間的接口描述語言與代碼生成和轉換工具
  • 採用二進制序列化傳輸數據

四、AXIS

源於 IBM "SOAP4J",使用 SOAP 協議

五、Mule ESB

基於 Java 語言的企業服務總線產品,能夠把多個異構系統經過總線模式集成在一塊兒

1.5.3 微服務

一、Spring Boot
【圖1-37 JEE時代,應用包含在容器內的架構圖】
clipboard.png

Spring Boot 相反,它將容器嵌入自啓動的 Jar 包中,在 Spring Boot 應用啓動時,內部啓動嵌入的容器
【Spring Boot 的容器包含在應用內的架構圖】
clipboard.png

Spring Boot 這種設計在微服務架構下有以下明顯有點:

  • 能夠建立獨立、自啓動的應用程序
  • 無需構建 War 包併發布到容器中,構建和維護 War 包、容器的配置和管理也須要成本
  • 經過 Maven 的定製化標籤,能夠快速構建 Spring Boot 的應用程序
  • 能夠最大化的自動化配置 Spring,而無需人工配置各項參數
  • 提供了產品話特色,如:性能分析、健康檢查和外部化配置
  • 無 XML 配置
  • 是 Spring Cloud 構建微服務架構的重要基礎

二、Netflix

提供服務發現、斷路器和監控、智能路由、客戶端負載均衡、易用的 REST 客戶端等服務化必須的功能

三、Spring cloud Netflix

  • 服務發現組件 Eureka
  • 容錯性組件 Hystrix
  • 智能路由組件 Zuul
  • 客戶端負載均衡組件 Ribbon

【圖 1-39 Spring Cloud Netfix 架構圖】
clipboard.png

【Netflix 交互流程】

  1. 服務在 Eureka 服務器實例註冊
  2. Zuul 做爲一個特殊的服務在 Eureka 上註冊並發現服務
  3. Zuul 做爲網關,將發現的服務導出給客戶端
  4. RestTemplate 和 FeignClient 使用簡單的服務調用方法調用服務一、服務2

【Netflix 特色】

  • 服務在 Eureka 註冊,由 Spring 管理的 Bean 來發現和調用
  • 經過配置的方式能夠啓動嵌入式的 Eureka 服務器
  • Feign 客戶端經過聲明的方式便可導入服務代理
  • Zuul 使用 Ribbon 服務實現客戶端負載均衡
  • 經過聲明的方式便可插入 Hystrix 的客戶端
  • 經過配置的方式便可啓動 Hystrix 面板服務器
  • 在 Spring 環境中能夠直接配置 Netflix 組件
  • Zuul 能夠自動註冊過濾器和路由器,造成一個反向代理服務器
  • Hystrix 面板能夠對服務的狀態進行監控,並提供容錯機制
相關文章
相關標籤/搜索