1. 程式人生 > 實用技巧 >2020最全面的微服務

2020最全面的微服務

Spring Cloud

初識Spring Cloud與微服務

  • 在傳統的軟體架構中,我們通常採用的是單體應用來構建一個系統,一個單體應用糅合了各種業務模組。起初在業務規模不是很大的情況下,對於單體應用的開發維護也相對容易。但隨著企業的發展,業務規模與日遞增,單體應用變得愈發臃腫。由於單體應用將各種業務模組聚合在一起,並且部署在一個程序內,所以通常我們對其中一個業務模組的修改也必須將整個應用重新打包上線。為了解決單體應用變得龐大脯腫之後產生的難以維護的問題,微服務架構便出現在了大家的視線裡

什麼是微服務

  • 微服務(Microservices)是一種軟體架構風格,起源於Peter Rodgers博士於 2005 年度雲端運算博覽會提出的微 Web 服務 (Micro-Web-Service) 。微服務主旨是將一個原本獨立的系統 拆分成多個小型服務,這些小型服務都在各自獨立的程序中執行,服務之間通過基於HTTP的RESTful API

    進行通訊協作。下圖展示了單體應用和微服務之間的區別:

  • 在微服務的架構下,單體應用的各個業務模組被拆分為一個單獨的服務並部署在單獨的程序裡,每個服務都可以單獨的部署和升級。這種去中心化的模式使得後期維護和開發變得更加靈活和方便,由於各個服務單獨部署,所以可以使用不同的語句來開發各個業務服務模組

什麼是Spring Cloud

  • Spring Cloud是一種基於Spring Boot實現微服務架構的開發工具。它的微服務架構中涉及的配置管理、服務治理、斷路器、智慧路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式。Spring Cloud的誕生並不是為了解決微服務中的某一個問題,而是提供了一套解決微服務架構實施的綜合性解決方案
  • Spring Cloud是一個由各個獨立專案組成的綜合專案,每個獨立專案有著不同的釋出節奏,為了管理每個版本的子專案清單,避免Spring Cloud的版本號與其子專案的版本號混淆,沒有采用版本號的方式,而是通過命名的方式。這些版本的名字採用了倫敦地鐵站的名字,根據字母表的順序來對應版本時間順序,比如“Angel”是Spring Cloud的第一個發行版名稱,‘Brixton’是Spring Cloud的第二個發行版名稱,當一個發行版本的Spring Cloud專案釋出內容積累到臨界點或者一個嚴重bug解決可用後,就會發佈一個”service releases”版本,簡稱SRX版本,其中X是一個遞增的數字,所以Brixton.SR5
    就是Brixton的第5個Release版本

上篇 Spring Boot 2.X版和Spring Cloud H版

版本選型

  • spring boot 版本選型

    1. git原始碼地址
    2. spring boot 2.0 新特性(官網強烈建議升級到2.x版本)
    3. 官網看boot版本
  • spring cloud版本選擇

    1. git原始碼地址
    2. 官網
    3. 官網看Cloud版本
      • 命名規則 採用了英國倫敦地鐵站名稱命名,並由地鐵站字母A-Z依次類推的形式來發布迭代版本
  • Spring cloud和Spring boot之間的依賴關係如何看

    1. 更詳細的版本檢視資訊

      • https://start.spring.io/actuator/info
      • 檢視json串返回結果

  • 版本確定(截止2020.2.15)

    1.cloud :Hoxston.SR1
    2.boot :2.2.2.RELEASE
    3.cloud alibaba :2.1.0.RELEASE
    4.Java :Java8
    5.Maven : 3.5及以上
    6.MySql :5.7及以上
    7.題外話:booot版本最新已經到2.2.4,為什麼選擇2.2.2?
    答:1. 只用boot 直接最新
       2. 同時使用boot和cloud 需照顧cloud 由Spring cloud來決定boot版本
    

關於Cloud 各種元件的停更/升級/替換

  • 由停更引發的“升級慘案”

    1. 停更不停用

      • 被動修復bugs
      • 不再接受合併請求
      • 不再發布新版本
    2. 明細條目

      • 以前
      • now 2020

搭建父工程

  • Maven結構
    1. dependency Management :Maven 使用dependency Management 元素來提供了一種管理依賴版本號的方式。通常會在一個組織或者專案的最頂層的父POM中看到dependency Management元素。
    2. 使用pom.xml中的dependency Management元素能夠讓所有在子專案中引用的一個依賴而不用顯式的列出版本號。Maven會沿著父子層次向上走,直到找到一個擁有dependency Management元素的專案,然後他就會使用這個dependency Management 元素中指定的版本號
    3. 這樣做的好處就是:如果有對個子專案都引用同一個依賴,則可以避免在每個使用的子專案裡都宣告一個版本號,這樣當想升級或者切換到另一個版本時,只需要在頂層父容器裡更新,而不需要一個一個子專案的修改;另外如果某個子專案需要另外的版本,只需要宣告version就可
    4. dependency Management 裡只是宣告依賴,並不實現引入,因此子專案需要顯式的宣告需要用的依賴。
    5. 如果不在子專案中宣告依賴,是不會從父專案中繼承下來的;只有在子專案中寫了該依賴項,並且沒有指定具體版本,才會從父專案中繼承該項,並且version和scope都讀取自父pom
    6. 如果子專案中指定了版本號,那麼就會使用子專案指定的jar包

微服務子模組構建

  • 微服務模組

    1. 建module
    2. POM
    3. YML
    4. 主啟動
    5. 業務類
  • 微服務執行

    1. 通過修改idea的 workspace.xml 的方式來快速開啟Run Dashboard視窗
    2. 開啟Run Dashboard
  • 熱部署Devtools

    1. Adding devtools to your project

      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
         <scope>runtime</scope>
          <optional>true</optional>
      </dependency>
      
    2. Adding plugin to your pom.xml

      下一段配置黏貼到父工程當中的pom裡
       
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <fork>true</fork>
              <addResources>true</addResources>
            </configuration>
          </plugin>
        </plugins>
      </build>
      
    3. Enabling automatic build

    4. Update the value of

    5. 重啟IDEA

  • (訂單支付服務遠端呼叫)原始方法

    1. RestTemplate 提供了多種便捷訪問遠端Http服務的方法,是一種簡單便捷的訪問restful服務模板類,是Spring提供的用於訪問Rest服務的客戶端模板工具集
    2. 使用restTemplate訪問restful介面非常簡單粗暴無腦,(url、requestMap、ResponseBean.class)這三個引數分別代表Rest請求地址、請求引數、HTTP響應轉換被轉換成的物件型別
  • 工程重構

    1. 重複程式碼 冗餘
    2. 建立公共模組

服務註冊與發現

Eureka服務註冊與發現

是什麼
  • Eureka基礎知識

    1. 什麼是服務治理:Spring Cloud 封裝了 Netflix 公司開發的Eureka模組來實現服務治理。
    2. 在傳統的rpc遠端呼叫框架中,管理每個服務與服務之間依賴關係比較複雜,管理比較複雜,所以需要使用服務治理,管理服務與服務之間依賴關係,可以實現服務呼叫、負載均衡、容錯等,實現服務發現與註冊。
  • 什麼是服務註冊

    1. Eureka採用了CS的設計架構,Eureka Server作為服務註冊功能的伺服器,它是服務註冊中心。而系統中的其他微服務,使用Eureka的客戶端連線到Eureka server 並維持心跳連線,這樣系統的維護人員就可以通過 Eureka Server 來監控系統中的各個微服務是否正常執行
    2. 在服務註冊與發現中,有一個註冊中心。當伺服器啟動的時候,會把當前自己的伺服器的資訊比如服務地址通訊等以別名的方式註冊到註冊中心上。另一方(消費者|服務提供者),以該別名的方式去註冊中心上獲取到實際的服務通訊地址,然後在實現本地RPC呼叫。RPC遠端呼叫框架核心設計思想:在於註冊中心,因為使用註冊中心管理每個服務與服務之間的一個依賴關係(服務治理概念)。在任何rpc遠端框架中,都會有一個註冊中心(存放服務地址相關資訊(介面地址))
  • Eureka的兩個元件

    1. Eureka Server:提供服務註冊服務

      各個微服務節點通過配置啟動後,會在Eureka Server中進行註冊,這樣Eureka Server中的服務登錄檔中將會儲存所有可用服務節點的資訊,服務節點的資訊可以在介面中直觀的看到。

    2. Eureka Client

      是一個Java客戶端,用於簡化Eureka Server 的互動,客戶端同時也具備一個內建的、使用輪詢(round-robin)負載演算法的負載均衡器。在應用啟動後,將會向Eureka Server傳送心跳(預設週期為30秒),如果Eureka server 在多個心跳週期內沒有收到某個節點的心跳,Eureka Server 將會從服務登錄檔中把這個服務節點移除(預設90秒)

怎麼用
  1. IDEA生成Eureka Server 端服務註冊中心(類似物業公司)

  2. Eureka Client 端 cloud-peovider-payment8001將註冊進Eureka Server成為服務提供者provider(類似學校提供授課服務)

    • Eureka Client yml配置

    • Eureka Client啟動類

  3. Eureka Client 端 cloud-consumer-order80將註冊進 Eureka Server 成為服務消費者consumer(類似上課消費的學生)

    • 如2的圖
  • 叢集的Eureka原理說明

    1. 微服務RPC遠端呼叫最核心是什麼: 高可用
    2. 解決辦法:搭建Eureka註冊中心叢集,實現負載均衡+故障容錯
    3. 互相註冊 相互守望
  • 叢集的Eureka的搭建步驟

    1. 修改對映配置 :找到C:\Windows\System32\drivers\etc路徑下的hosts檔案

    2. 新增進hosts檔案:

      1. 127.0.0.1 eureka7001
      2. 127.0.0.1 eureka7002
    3. 編寫yml

    4. 啟動類

  • 將支付服務8001 釋出到兩臺eureka叢集配置中

    1. 其他配置不需要動

    2. 修改eureka配置的defaultZone

  • Eureka叢集服務

  • 支付服務者提供者8001叢集環境搭建

    1. 複製8001服務為8002

    2. application name 一致

    3. 80消費8001/8002 服務地址不能寫死,在微服務中 統一呼叫application name

    4. 使用@LoadBalanced

    5. 註解賦予RestTemplate負載均衡的能力

    6. 測試結果

      1. 先要啟動EurekaServer,7001/7002服務
      2. 再要啟動服務提供者provider,8001/8002服務
      3. 負載均衡埠效果達到 8001/8002埠交替出現
      4. Ribbon和Eureka整合後Consumer可以直接呼叫服務不用再關心地址和埠號,且該服務還有負載均衡功能
  • actuator微服務資訊完善

    1. 主機名稱:服務名稱修改·
      1. yml eureka.instance.instance-id
    2. 訪問資訊有IP資訊提示
      1. yml eureka,instance.prefer-ip-address:true
  • Eureka服務發現Discovery

    1. 對於註冊進eureka裡面的微服務,可以通過服務發現來獲得該服務的資訊
    2. controller DiscoveryClient
    3. Application啟動類 新增 @EnableDiscoveryClient註解
  • Eureka自我保護

    1. 概述:保護模式主要用於一組客戶端和Eureka Server之間存在的網路分割槽場景下的保護,一旦進入保護模式,Eureka Server將會嘗試保護去服務登錄檔中的資訊,不再刪除服務登錄檔中的資料,也就是不會登出任何微服務

      1. 一句話:某時刻某一個微服務不可用了,Eureka不會立刻清理,依舊會對該微服務的資訊進行儲存。屬於CAP裡面的AP分支
    2. 為什麼會產生Eureka自我保護機制

      1. 為了防止EurekaClient可以正常執行,但是與EurekaServer網路不通的情況下,EurekaServer不會立刻將EurekaClient服務剔除
      2. 什麼是自我保護機制:當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網路分割槽故障),那麼這個節點就會進入自我保護模式
      3. 在自我保護模式中,Eureka Server會保護服務登錄檔中的資訊,不再登出任何服務例項。它的設計哲學就是寧可保留錯誤的服務註冊資訊,也不盲目登出任何可能健康的服務例項(好死不如賴活著)
      4. 綜上,自我保護模式是一種應對網路異常的安全保護措施,它的架構哲學是寧可同時保留所有的微服務(健康的微服務和不健康的微服務都會保留)也不會盲目的登出任何健康的微服務。使用自我保護模式,可以讓Eureka叢集更加的健壯、穩定
    3. Eureka服務停更說明:停更不停用

Zookeeper服務註冊與發現

是什麼
  • Zookeeper概述

    • Zookeeper是一個開源的,分散式系統狀態下的,多系統之間的協調排程、通知機制以達到一致性原則的一個服務功能架構
    • 管理者
  • 設計模式來理解

    • 是一個基於觀察者模式設計的分散式服務管理框架,它負責儲存和管理大家都關心的資料,然後接受觀察者的註冊,一旦這些資料的狀態發生變化,Zookeeper就將負責通知已經在Zookeeper上註冊的那些觀察者做出相應的反應,從而實現叢集中類似的Master/Slave管理模式。
  • 一句話理解

  • 檔案系統+通知機制

  • Zookeeper安裝

    1. 官網下載

    2. 解壓 tar -zxvf

    3. conf資料夾中 zoo_sample.cfg引數解讀

      • tickTime :通訊心跳數Zookeeper伺服器心跳時間,單位毫秒。用於心跳機制,並且設定最小的session超時時間為兩倍心跳時間(session的最小超時時間為2*tickTime
      • initLimit:LF初識通訊時限(follower和leader):叢集中follower跟隨者伺服器(F)與leader領導者伺服器(L)之間初始連線時能容忍的最多心跳數(tickTime的數量),用它來限定叢集中的Zookeeper伺服器連線到Leader的時限
      • syncLimit:LF同步通訊時限:叢集中Leader與Follower之間的最大響應時間單位,假如響應超過syncLimit*tickTime,Leader認為Follower死掉,從伺服器列表中刪除Follower
      • dataDir:實際儲存位置
      • clientPort:預設埠號
    4. 開啟服務+客戶端連線

      • 啟動 ./zkServer.sh start

      • 關閉 ./zkServer.sh stop

      • 客戶端連線 ./zkCli.sh

      • 退出 quit

      • 檢視服務是否啟動: ps -ef|grep zookeeper|grep -v grep

      • 建立+刪除節點:create /testNode v1

        delete /testNode

        set /testNode v2

        get /testnode

    5. 檢視+獲取zookeeper伺服器上的資料儲存資訊

      • 檔案系統:Zookeeper維護一個類似檔案系統的資料結構,所使用的的資料模型風格很像檔案系統的目錄樹結構,簡單來說,有點類似windows中登錄檔的結構,有名稱,有樹節點,有Key/Value 的關係,可以看做一個樹形結構的資料庫,分佈在不同的機器上做名稱管理

      • 初識znode節點:Zookeeper資料模型的結構與Unix檔案系統很類似,整體上可以看做是一棵樹,每個節點稱作一個Znode,很顯然zookeeper叢集自身維護了一套資料結構,這個儲存結構是一個樹形結構,其上每一個節點,我們稱之為“znode”,每一個znode預設能夠儲存1MB的資料,每個znode都可以通過其路徑唯一標識。

      • 資料模型/znode節點深入:

        1. Znode的資料模型

          • 是什麼 (/stat)zookeeper內部維護了一套型別UNIX的樹形資料結構,由znode構成的集合,znode的集合又是一個樹形結構,每一個znode又有很多屬性進行描述。Znode=path+nodeValue+Stat
          • zookeeper的Stat結構體
            1. czxid:引起這個znode建立的zxid,建立節點的事務的zxid(Zookeeper Transaction Id)
            2. ctime:znode被建立的毫秒數(從1970年開始)
            3. mzxid:znode最後更新的zxid
            4. mtime:znode最後修改的毫秒數(從1970年開始)
            5. pZxid:znode最後更新的子節點zxid
            6. cversion:znode子節點變化號,znode子節點修改次數
            7. dataversion:znode資料變化號
            8. aclVersion:znode訪問控制列表的變化號
            9. ephemeralOwner:如果是臨時節點,這個是znode擁有者的session id,如果不是臨時節點則是0
            10. dataLength:znode的資料長度
            11. numChildren:znode子節點數量
        2. znode的存在型別

          • 持久

            1. PERSISTENT:持久化目錄節點 客戶端與zookeeper斷開連線後,該節點依舊存在
            2. PERSISTENT_SEQUENTIAL:持久化順序編號目錄節點 客戶端與zookeeper斷開連線後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
          • 臨時

            1. EPHEMERAL:臨時目錄節點 客戶端與zookeeper斷開連線後,該節點被刪除

            2. EPHEMERAL_SEQUENTIAL:臨時順序編號目錄節點 客戶端與zookeeper斷開連線後,該節點被刪除,只有Zookeeper給該節點名稱進行順序編號

          • create /name create -e /name create -s /name create -e -s /name -s:代表序列號 -e:代表臨時 什麼都不加代表p:持久化

  • 典型應用場景(能幹嘛)

  1. 命名服務
  2. 配置維護
  3. 叢集管理
  4. 分散式訊息同步和協調機制
  5. 負載均衡
  6. Dubbo的支援
  7. 備註:ZooKeeper提供了一套很好的分散式叢集管理的機制,就是它這種基於層次型的目錄樹的資料結構,並對樹中節點進行有效管理。從而可以設計出多種多樣的分散式的資料管理模型,作為分散式系統的溝通排程橋樑
  • 實際運用(怎麼玩)

    1. 統一命名服務(Name Service如Dubbo服務註冊中心)
    2. 配置管理(Configuration Management如淘寶開源配置框架Diamond)
    3. 叢集管理(Group Membership如Hadoop分散式叢集管理)
    4. Java操作API
  • 基礎命令和Java客戶端操作

    • zkCli的常用命令操作

      1. redisKV鍵值對類似,只不過key變成了一個路徑節點值,v就是data。 Zookeeper表現為一個分層的檔案系統目錄樹結構,不同於檔案系統之處在於:zk節點可以有自己的資料,而unix檔案系統中的目錄節點只有子節點。 一個節點對應一個應用,節點儲存的資料就是應用需要的配置資訊
      2. 常用命令:
        1. help
        2. ls
        3. ls2: 是否有結構體 stat的內容
        4. stat
        5. set
        6. get
        7. create
        8. delete
        9. rmr
    • 四字命令

      • 是什麼

        1. zookeeper支援某些特定的四字命令,他們大多是用來查詢ZK服務的當前狀態及相關資訊的,通過telnet或nczookeeper提交相應的命令,如echo | ruok | nc 127.0.0.1 2181 得到結果 imok 啟動正常
        2. 執行公式:echo 四字命令 | nc 主機IP zookeeper
      • 常用命令

        1. ruok:測試服務是否處於正確狀態,如果確實如此,返回imok,否則不做任何響應
        2. stat:輸出關於效能和連線的客戶端列表
        3. conf:輸出相關服務配置的詳細資訊
        4. cons:列出所有連線到伺服器的客戶端的完全的連線/會話的詳細資訊。包括接受/傳送的包數量、
        5. dump:列出未經處理的會話個臨時節點
        6. envi:輸出關於服務環境的詳細資訊(區別於conf命令)
        7. reqs:列出未經處理的請求
        8. wchs:列出伺服器watch的詳細資訊
        9. wchc:通過session列出伺服器watch的詳細系資訊,它的輸出是一個與watch相關的會話的列表
        10. wchp:通過路徑列出伺服器watch的詳細資訊,它輸出一個與session相關的路徑
    • java客戶端操作

      • zkclient zookeeperjar包匯入
  • 通知機制

    • session是什麼

    • watch

      1. 通知機制:客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(資料改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端

      2. 是什麼

        • 觀察者的功能:
          1. ZooKeeper支援watch(觀察)的概念。客戶端可以在每個znode節點上設定一個觀察。如果被觀察服務端的znode變更,那麼watch就會被觸發,這個watch所屬的客戶端將接收到一個通知包被告知節點已經發生變化,把相應的時間通知給設定watch的Client端
          2. ZooKeeper裡的所有讀取操作:getData()、getChildren()和exists()都有設定watch的選項
        • 一句話:非同步+回撥+觸發機制
      3. watch事件理解:

        1. 一次觸發(one-time trigger):
          • 當資料發生變化時,zkserver向客戶端傳送一個watch,它是一次性的動作,即觸發一次就不再有效,類似一次性紙杯。
          • 只監控一次
          • 如果想繼續watch的話,需要客戶端重新設定watcher,因此如果你得到一個watch事件且想在將來的變化得到通知,必須重新設定另一個watch
        2. 傳送客戶端(send to client):Watchers是非同步發往客戶端的,ZooKeeper提供一個順序保證:在看到watch事件之前絕不會看到變化,這樣不同客戶端看待的是一致性的順序。
        3. 為資料設定watch:節點有不同的改變方式,可以認為ZooKeeper維護兩個觀察列表:資料觀察和子節點觀察getData、exists設定資料觀察,getChildren設定子節點觀察。setData將為znode觸發資料觀察。成功的create將為建立節點觸發資料觀察,為其父節點觸發子節點觀察。delete觸發節點的資料觀察以及子節點觀察,為其父節點觸發子節點觀察
        4. 時序性和一致性
        5. 變化備註
          • data watches and child watches
          • watch之資料變化
          • watch之節點變化
      4. code

        • 一次性 one-time trigger -------WatchOne
        • 多次(命名服務------WatchMore
        • 子節點----WatchChild
  • ZooKeeper叢集

    • 是什麼

      • ZooKeeper分為2部分:伺服器端和客戶端,客戶端只連線到整個ZooKeeper服務的某個伺服器上。客戶端使用並維護一個TCP連線,通過這個連線傳送請求、接受響應、獲取觀察的事件以及傳送心跳。如果這個TCP連線中斷,客戶端將嘗試連線到另外一個ZooKeeper伺服器。客戶端第一次連線到ZooKeeper服務時,接受這個連線的ZooKeeper伺服器會為這個客戶端建立一個會話。當這個客戶端連線到另外的伺服器時,這個會話會被新的伺服器重新建立。
    • 偽分散式單機配置

      • 說明

        • 伺服器名稱與地址:叢集資訊(伺服器編號,伺服器地址,LF通訊埠,選舉埠)

        • 這個配置項的書寫格式比較特殊,規則如下:server.N=YYY:A:B ,其中

        • N表示伺服器編號,

        • YYY表示伺服器的IP地址,

        • A為LF通訊埠,表示該伺服器與叢集中的leader交換的資訊埠(leader follower/master slave 主從通訊埠)

        • B為選舉埠,表示選舉新Leader時伺服器間相互通訊的埠(當leader掛掉時,其餘伺服器會相互通訊,選擇出新的leader)

        • 一般來說,叢集中每個伺服器的A埠都是一樣,每個伺服器的B埠也是一樣。下面是一個叢集的例子:

          • server.0=233.34.9.144:2008:6008
          • server.1=233.34.9.145:2008:6008
          • server.2=233.34.9.146:2008:6008
          • server.3=233.34.9.147:2008:6008
        • 但是當所採用的的為叢集時,IP地址都是一樣的,只能是A埠和B埠不一樣:

          • server.0=127.0.0.1:2008:6008
          • server.1=127.0.0.1:2007:6007
          • server.2=127.0.0.1:2006:6006
          • server.3=127.0.0.1:2005:6005
      • 配置步驟

        1. zookeeper.tar.gz解壓後拷貝到/zookeeper目錄下並重命名為zk01,在複製zk01形成zk02zk03
        2. 進入zk01/2/3 分別新建資料夾 mydatamylog
        3. 分別進入zk01/2/3各自的conf 新增zoo.cfg
        4. 編輯zoo.cfg
        5. 在各自mydata下面建立myid的檔案,在裡面寫入server的數字
        6. 分別啟動三個伺服器
        7. zkCli連線server,帶引數指定 -server:./zkCli.sh -server 127.0.0.1:2191
SpringCloud整合ZooKeeper代替Eureka
  • 註冊中心ZooKeeper

    1. ZooKeeper是一個分散式協調工具,可以實現註冊中心功能
    2. 關閉Linux伺服器防火牆後啟動ZooKeeper伺服器
    3. ZooKeeper伺服器取代Eureka伺服器,ZK作為服務註冊中心
  • 服務提供者

    • cloud-provider-payment8004
    • 服務節點是臨時性的 心跳檢測機制:一定時間內為收到心跳包 就移除。
    • CAP:一致性(Consistency)、高可用(Availability)、分割槽容錯性(Partition tolerance)。CAP 原則指的是:這三個要素最多隻能同時實現兩點,不可能三者兼顧
  • 服務消費者

    • cloud-consumerzk-order80

Consul服務註冊與發現

是什麼
  • Consul是HashiCorp公司推出的開源工具,用於實現分散式系統的服務發現與配置。Consul是分散式的、高可用的、 可橫向擴充套件的。它具備以下特性:
    • 服務發現: Consul提供了通過DNS或者HTTP介面的方式來註冊服務和發現服務。一些外部的服務通過Consul很容易的找到它所依賴的服務。
    • 健康檢測: Consul的Client提供了健康檢查的機制,可以通過用來避免流量被轉發到有故障的服務上。
    • Key/Value儲存: 應用程式可以根據自己的需要使用Consul提供的Key/Value儲存。 Consul提供了簡單易用的HTTP介面,結合其他工具可以實現動態配置、功能標記、領袖選舉等等功能。
    • 多資料中心: Consul支援開箱即用的多資料中心. 這意味著使用者不需要擔心需要建立額外的抽象層讓業務擴充套件到多個區域。
  • 下載安裝並執行
    • 具體方法官網都有
    • win:進入consul.exe所在目錄--->cmd--->consul --version (檢視版本資訊) --->consul agent -dev 啟動
    • http://localhost:8500 訪問頁面
怎麼用
  • 服務提供者
    • cloud-providerconsul-payment8006
  • 服務消費者
    • cloud-consumerconsul-order80
三個註冊中心的異同點(Eureka、ZooKeeper、Consul)
  • 元件名 語言 CAP 服務健康檢測 對外暴露介面 SpringCloud整合
    Eureka Java AP 可配支援 HTTP 已整合
    ZooKeeper Java CP 支援 客戶端 已整合
    Consul Go CP 支援 HTTP/DNS 已整合
  • CAP

    • C:Consistency(強一致性)
    • A:Availability(可用性)
    • P:Partition tolerance(分割槽容錯性)
    • CAP理論關注粒度是資料,而不是整體系統設計的
  • 經典CAP圖

    • AP(Eureka)
    • CP(Zookeeper/Consul)

Ribbon負載均衡服務呼叫

概述
  • Spring Cloud Ribbon是基於NetFlix Ribbon實現的一套客戶端負載均衡的工具。簡單地說,Ribbon是NetFlix釋出的開源專案,主要功能是提供客戶端的軟體負載均衡演算法和服務呼叫。Ribbon客戶端元件提供一系列完善的配置項如連線超時,重試等。簡單的說,就是在配置檔案中列出Load Balancer(簡稱LB)後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連線等)去連線這些機器。我們很容易使用Ribbon實現自定義的負責均衡演算法。
能幹嘛
  • LB(Load Balance)負責均衡:將使用者的請求平攤的分配到多個伺服器上,從而達到系統的HA(高可用),常見的負載均衡有軟體NginxLVS硬體F5

    • 集中式LB
      • 即在服務的消費方和提供方之間是有獨立的LB設施(可以是硬體,如F5,也可以是軟體,如nginx),由該設施負責把訪問請求通過某種策略轉發至服務的提供方
    • 程序式LB
      • 將LB邏輯整合到消費方,消費方從服務註冊中心獲知到有哪些地址可用,然後自己再從這些地址中選擇出一個合適的伺服器。
      • Ribbon就屬於程序內的LB,它只是一個類庫,集成於消費方程序,消費方通過它來獲取到服務提供方的地址。
  • Ribbon本地負責均衡客戶端 vs Nginx服務端負載均衡區別

    • Nginx是伺服器負載均衡,客戶端所有請求都會交給Nginx,然後由nginx實現轉發請求。即負載均衡是由服務端實現的
    • Ribbon本地負載均衡,在呼叫微服務介面時,會在註冊中心上獲取註冊資訊服務列表之後快取到JVM本地,從而在本地實現RPC遠端服務呼叫技術。
    • 一句話總結:負載均衡+RestTemplate呼叫
Ribbon負責均演示
  • 架構說明

    • 總結:Ribbon其實就是一個軟負載均衡的客戶端元件,它可以和其他需要請求的客戶端結合使用,和eureka結合只是其中的一個例項。
    • Ribbon在工作時分成兩步
      • 第一步先選擇EurekaServer,它優先選擇在同一個區域內負載較少的server
      • 第二步再根據使用者指定的策略,再從server取到的服務註冊列表中選擇一個地址
      • 其中Ribbon提供了多種策略:比如輪詢、隨機和根據響應時間加權
    • Eureka中的 spring-cloud-stater-netflix-eureka-client 引入了Ribbon
  • 二說RestTemplate的使用

    • getForObject方法/getForEntity方法
      • getForObject方法:返回物件為響應體中資料轉化成的物件,基本可以理解為Json
      • getForEntity方法:返回物件為ResponseEntity物件,包含了響應中的一些重要資訊,比如響應頭、響應狀態嗎、響應體等。
    • postForObject/postForEntity
    • GET請求方法
    • POST請求方法
Ribbon核心元件IRule
  • IRule:根據特定演算法從服務列表中選取一個要訪問的服務
    1. com.netflix.loadbalancer.RoundRobinRule 輪詢
    2. com.netflix.loadbalancer.RandomRule 隨機
    3. com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試
    4. WeightedResponseTimeRuleRoundRobinRule的擴充套件,響應速度越快的例項選擇權重越大,越容易被選擇
    5. BestAvailableRule 會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最小的服務
    6. AvailabilityFilteringRule 先過濾掉故障例項,再選擇併發較小的例項
    7. ZoneAvoidanceRule 預設規則,複合判斷server所在區域的效能和server的可用性選擇伺服器
  • 如何替換負載均衡策略
    • 修改cloud-consumer-order80
    • 配置細節:官方文件明確給出了警告:這個自定義配置類不能放在@ComponentScan所掃描的當前包下以及子包下,否則我們自定義的這個配置類就會被所有的Ribbon客戶端所共享,達不到特殊定製化的目的了。
    • 新建package 不能跟主啟動類所在包同包以及其子包
    • 新建自定義規則的配置類
    • 主啟動類新增@RibbonClient註解,指定服務名稱以及自定義規則類
Ribbon負責均衡演算法剖析
  • 原理
    • 負載均衡演算法(輪詢):rest介面第幾次請求數 % 伺服器叢集總數量 =實際呼叫伺服器位置下標,每次服務重啟後,rest介面計數從1開始
  • 原始碼
    • 繼承了AbstractLoadBalancerRule抽象類
  • 手寫
    • 原理+JUCCAS+自旋鎖)
      1. 7001,7002叢集啟動
      2. 8001/8002微服務改造
      3. 80訂單微服務改造

OpenFeign服務

概述
  • OpenFeign是什麼

    • Fegin是一個宣告式Web Service客戶端。使用Feign能讓編寫Web Service客戶端更簡單。它的使用方法是定義一個服務介面然後在上面添加註解。Fegin也支援可拔插式的編碼器和解碼器。Spring Cloud對Fegin進行了封裝,使其支援了Spring MVC標準註解和HttpMessageConvertersFegin可以與Eureka和Ribbon組合使用以支援負載均衡
  • 能幹嘛

    • Fegin旨在使編寫Java Http客戶端變得更容易
    • 前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模板化的呼叫方法。但是在實際開發中,由於對服務依賴的呼叫可能不止一處,往往介面會被多處呼叫,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的呼叫。所以,Fegin在此基礎上做了一進一步封裝,由他來幫助我們定義和實現依賴服務介面的定義。在Fegin的實現下,我們只需要建立一個介面並使用註解的方式來配置它(以前是Dao介面上面標註Mapper註解,現在是一個微服務介面上面標註一個Fegin註解即可),即可完成對服務提供方的介面繫結,簡化了使用Spring cloud Ribbon時,自動封裝服務呼叫客戶端的開發量。
    • Fegin集成了Ribbon
      • 利用Ribbon維護了Payment的服務列表資訊,並且通過輪詢的方式實現了客戶端的負載均衡。而與Ribbon不同的是,通過Fegin只需要定義服務繫結介面且以宣告式的方法,優雅而簡單的實現了服務呼叫
  • Fegin與OpenFegin兩者區別

OpenFegin使用步驟
  • 建立一個介面並使用註解的方式來配置它:微服務呼叫介面+註解(@FeignClient)

  • 代替原有的Ribbon+RestTemplate的服務呼叫模式

OpenFegin超時控制
  • 超時設定,故意設定超時演示出錯情況
    1. 服務提供方8001,故意寫暫停程式
      2. 服務消費方80新增超時方法PaymentFeignService
  • OpenFeign客戶端預設等待一秒,但是伺服器端處理需要超過1秒鐘,導致OpenFeign客戶端不想等待了,直接返回報錯。為了避免這樣的情況,有時候我們需要設定feign客戶端的超時控制。
  • OpenFeign預設支援Ribbon
    • yml檔案中開啟配置
OpenFegin日誌列印功能
  • 日誌級別

    1. NONE:磨人的,不顯示任何日誌
    2. BASIC:僅記錄請求方法、URL、響應狀態碼及執行時間
    3. HEADERS:除了BASIC中定義的資訊之外,還有請求和響應的頭資訊
    4. FULL:除了HEADERS中定義的資訊之外,還有請求和相應的正文及元資料
  • 配置日誌Bean

  • yml檔案開啟日誌


服務降級

Hystrix斷路器

概述
  • 分散式系統面臨的問題
    • 複雜分散式體系結構中的應用程式有數十個依賴關係,每個依賴關係在某些時候將不可避免的失敗
    • 服務雪崩:多個微服務之間呼叫的時候,假設微服務A呼叫微服務B和微服務C,微服務B和微服務C又呼叫其他的微服務,這就是所謂的“扇出”。如果扇出的鏈路上某個微服務的呼叫響應時間過長或者不可用,對微服務A的呼叫就會佔用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩效應”。
    • 對於高流量的應用來說,單一的後端依賴可能會導致所有伺服器上的所有資源都在幾秒鐘內飽和。比失敗更糟糕的是,這些應用程式還可能導致服務之間的延遲增加,備份佇列,執行緒和其它系統資源緊張,導致整個系統發生更多的級聯故障。這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關係的失敗,不能取消整個應用程式或系統。
    • 所以,通常當你發現一個模組下的某個例項失敗後,這時候這個模組依然還會接收流量,然後這個有問題的模組還需要呼叫其他模組,這樣就會發生級聯故障,或者叫做雪崩
  • 是什麼
    • Hystrix是一個用於處理分散式系統的延遲容錯的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整個服務失敗,避免級聯故障,以提高分散式系統的彈性
    • “斷路器”本身是一種開關裝置,當某個服務單元發生故障後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要的佔用,從而避免了故障在分散式系統中的蔓延,乃至雪崩。
  • 能幹嘛
    • 服務降級
    • 服務熔斷
    • 接近實時的監控
    • 。。。。。。(限流、隔離)
  • Hystrix官宣,停更進維
Hystrix重要概念
  • 服務降級--fallback(備選響應)
    • 伺服器忙,請稍後再試,不讓客戶端等待並立刻返回一個友好提示,fallback
    • 哪些情況會觸發降級:
      1. 程式執行異常
      2. 超時
      3. 服務熔斷觸發降級
      4. 執行緒池/訊號量打滿也會導致服務降級
  • 服務熔斷--break
    • 類比保險絲達到最大服務訪問後,直接拒絕訪問,拉閘限電,然後呼叫服務降級的方法並返回友好提示
    • 就是保險絲:服務的降級---進而熔斷---恢復呼叫鏈路
  • 服務限流--flowlimit
    • 秒殺高併發等操作,嚴禁一窩蜂的過來擁擠,大家排隊,一秒鐘N個,有序進行
Hystrix案例
  • 新建cloud-provider-hystrix-payment8001

  • 高併發測試 jemeter

    • 開啟Jmeter,來20000個併發壓死8001,20000個請求都去訪問paymentInfo_timeout服務
    • 演示結果:出現卡頓,tomcat的預設工作執行緒數被打滿了,沒有多餘的執行緒來分解壓力和處理
  • 壓測結論

  • 上面還是服務提供者8001自己測試,假如此時外部的消費者80也來訪問,那消費者只能乾等,最終導致消費端80不滿意,服務端8001直接被拖死

  • 看熱鬧不嫌事大,80新建加入

    • cloud-consumer-feign-hystrix-order80
    • 繼續壓測 8001自測以及80呼叫服務
  • 故障現象和導致原因

    • 8001同一層次的其他介面服務被困死,因為tomcat執行緒裡面的工作執行緒已經被擠佔完畢
    • 80此時呼叫8001,客戶端訪問響應緩慢,轉圈圈
  • 結論:正因為有上述故障或不佳表現,才有我們的降級/容錯/限流等技術誕生

  • 如何解決?解決的要求

    • 超時導致伺服器變慢(轉圈)----超時不再等待
    • 出錯(宕機或程式執行出錯)----出錯要有兜底
    • 解決
      • 對方服務(8001)超時了,呼叫者(80)不能一直卡死等待,必須有服務降級
      • 對方服務(8001)宕機了,呼叫者(80)不能一直卡死等待,必須有服務降級
      • 對方服務(8001)OK,呼叫者(80)自己出故障或有自我要求(自己的等待時間小於服務提供者)自己處理降級
  • 服務降級

    • 降級的配置 @HystrixCommand註解

    • 8001先從自身找問題:設定自身呼叫的超時時間峰值,峰值內可以正常執行,超過l需要有兜底的方法處理,作服務降級fallback

    • 8001 fallback

      • 業務類啟用
      • 主啟動類啟用 新增新註解 @EnableCircuitBreaker
    • 80fallback

      • 80訂單微服務,也可以更好的保護自己,自己也依樣畫葫蘆進行客戶端降級保護
    • 目前問題:

      • 每個業務方法對應一個兜底的方法,程式碼膨脹、冗餘
      • 統一和自定義的分開
    • 待解決問題

      • 每個方法配置一個???程式碼冗餘
        1. 註解@DefaultProperties(defaultFallback = "通用處理方法名")
        2. 除了特別重要的核心業務有專屬,其他普通的可以通過@DefaultProperties(defaultFallback ="")統一跳轉到統一處理結果頁面
        3. 通用的和獨享的各自分開,避免了程式碼膨脹,合理減少了程式碼量
      • 和業務邏輯混合在一起???亂!
        • 服務降級,客戶端去呼叫服務端,碰上服務端宕機或關閉
        • 本次案例服務降級處理是在客戶端80實現的,與服務端8001沒有關係,只需要為Feign客戶端定義的介面新增一個服務降級處理的實現類即可實現解耦
        • 未來我們要面對的異常:執行超時、宕機
        • 根據cloud-consumer-feign-hystrix-order80已經有的PaymentHystrixService介面,重新新建一個類(PaymentFallbackServiceImpl)實現該介面,統一為接口裡面的方法進行異常處理
          1. yml檔案
          2. PaymentHystrixService介面,指定降級處理類。
          3. 客戶端自己的提升:此時服務端provider已經down了,但是我們做了服務降級處理,讓客戶端在服務端不可用時也會獲得提示資訊而不會掛起耗死伺服器
  • 服務熔斷

    • 斷路器

    • 熔斷是什麼

      • 熔斷機制概述:熔斷機制是應對雪崩效應的一種微服務鏈路保護機制,當扇出鏈路的某個微服務出錯不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的呼叫,快速返回錯誤的響應資訊。當檢測到該節點微服務呼叫響應正常後,恢復呼叫鏈路
      • 在Spring Cloud框架裡,熔斷機制通過Hystrix實現,Hystrix會監控微服務間的呼叫狀況,當失敗的呼叫到一定閾值,預設是5秒內20次呼叫失敗,就會啟動熔斷機制,熔斷機制的註解是@HysrixCommand
    • 實操

      • 修改cloud-provider-hystrix-payment8001
      • service介面
      • 重點測試:多次錯誤,然後慢慢正確,發現剛開始不滿足條件,就算是正確的訪問地址也不能進行訪問,需要慢慢的恢復鏈路
    • 原理(小總結)

      • 大神理論:

      • 熔斷型別:

        • 熔斷開啟:請求不再進行呼叫當前服務,內部設定時鐘一般為MTTR(平均故障處理時間),當開啟時長達到所設時鐘則進入半熔斷狀態
        • 熔斷關閉:熔斷關閉不會對服務進行熔斷
        • 熔斷半開:部分請求根據規則呼叫當前服務,如果請求成功並且符合規則則認為當前服務恢復正常,關閉熔斷
      • 官網斷路器流程

        • 流程圖

        • 官網步驟

        • 斷路器在什麼情況下開始起作用

        • 斷路器開啟或者關閉的條件

          1. 當請求滿足一定閾值的時候(預設10秒內超過20個請求次數)
          2. 並且失敗率達到一定值的時候(預設10秒內超過50%的請求失敗)
          3. 到達以上閾值,斷路器將會開啟
          4. 當開啟的時候,所有請求都不會進行轉發
          5. 一段時間之後(預設是5秒),這個時候斷路器是半開狀態,會讓其中一個請求進行轉發。如果成功,斷路器會關閉,若失敗,繼續開啟。重複4和5
        • 斷路器開啟之後

          • 開啟之後,再有請求呼叫的時候,將不會呼叫主邏輯,而是直接呼叫降級fallback,通過斷路器,實現了自動地發現錯誤並將降級邏輯切換為主邏輯,減少響應延遲的效果。
          • 原來的主邏輯要如何恢復呢? -----對於這一問題,hystrix也為我們實現了自動恢復功能。當斷路器開啟,對主邏輯進行熔斷之後,hystrix會啟動一個休眠的時間窗,在這個時間窗內,降級邏輯是臨時的成為主邏輯,當休眠時間窗到期,斷路器將進入半開狀態,釋放一次請求到原來的主邏輯上,如果此次請求正常返回,那麼斷路器將繼續閉合,主邏輯恢復,如果這次請求依然有問題,斷路器繼續進入開啟狀態,休眠時間窗重新計時。
        • ALL配置

  • 服務限流

    • 後面講解alibaba的Sentinel說明
Hystrix工作流程
服務監控HystrixDashboard
  • 概述
  • 儀表盤9001
    • 新建cloud-consumer-hystrix-dashboard9001
    • POM
    • YML
    • HystrixDashboardMain9001+新註解@EnableHystrixDashboard
    • 所有Provider微服務提供類(8001/8002/8003)都需要監控依賴配置
    • 啟動cloud-consumer-hystrix-dashboard9001該微服務後續將監控微服務8001
  • 斷路器演示
    • 修改cloud-provider-hystrix-payment8001
      • 注意圖形化展示:spring-boot-starter-actuator(必須有)
      • 注意:新版本Hystrix需要在主啟動類MainAppHystrix8001中指定監控路徑
      • 填寫監控地址:http://localhost:8001/hystrix.stream
      • 先訪問正確地址,再訪問錯誤地址,再正確地址,會發現圖示斷路器都是慢慢放開的(closed---->open 斷路器開啟 open--->close 斷路器關閉)
  • 如何看監控介面:
    • 7色:每種顏色對應不同的故障
    • 1圈:實心圈。共有兩種含義,它通過顏色的變化代表了例項的健康程度,它的健康度從 綠色<黃色<橙色<紅色遞減。該實心圈除了顏色的變化之外,它的大小也會根據例項的請求流量發生變化,流量越大該實心圓就越大。所以通過該實心圓的展示,就可以在大量的例項中快速的發現故障例項和高壓力例項
    • 1線:曲線。用來記錄2分鐘內流量的相對變化,才可以通過它來觀察到流量的上升和下降的趨勢。
    • 整個圖的說明:
    • 複雜的

服務閘道器

Gateway新一代閘道器

概述簡介
  • 官網:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

  • 是什麼

    • 概述
      • SpringCloud Gateway是Spring Cloud的一個全新專案,它旨在為微服務架構提供一種簡單有效的統一的API路由管理方式
      • 為了提高閘道器的效能,SpringCloud Gateway是基於WebFlux框架實現的,而WebFlux框架底層則使用了高效能的Reactor模式通訊框架Netty
      • SpringCloud Gateway的目標提供統一的路由方式且基於Filter鏈的方式提供了閘道器基本的功能,例如:安全,監控/指標和限流
    • 一句話:Spring Cloud Gateway 使用的Webflux中的reactor-netty響應式程式設計元件,底層使用了Netty通訊
  • 能幹嘛

    • 反向代理
    • 鑑權
    • 流量控制
    • 熔斷
    • 日誌監控
    • ......
  • 微服務架構中閘道器在哪裡

  • 為什麼選擇使用Gateway

    • 1.neflix不太靠譜,zuul2.0一直跳票,遲遲不釋出
    • Spring Cloud Gateway 具有如下特性:
      • 基於Spring Framework 5,Project Reactor和Spring Boot2.0進行構建
      • 動態路由:能夠匹配任何請求屬性
      • 可以對路由指定Predicate(斷言)和Filter(過濾器)
      • 整合Hystrix的斷路器功能
      • 整合Spring Cloud 服務發現功能
      • 易於編寫的Predicate(斷言)和Filter(過濾器)
      • 請求限流功能
      • 支援路徑重寫
    • Spring Cloud Gateway和Zuul的區別
      • Zuul 1.x,,是一個基於阻塞I/O的API閘道器
      • Zuul 2.x 理念更先進,想基於Netty非阻塞和支援長連線,但SpringCloud目前還沒有整合。Zuul 2.x的效能比Zuul 1.x有較大的提升。在效能方面,根據官方提供的測試基準,Spring Cloud Gateway的RPS(每秒請求數)是Zuul的1.6倍
      • Spring Cloud Gateway建立在Spring Framework5、Project Reator和Spring Boot 2之上,使用非阻塞API
      • Spring Cloud Gateway還支援WebSocket,並且與Spring緊密整合擁有更好的開發體驗
  • Zuul 1.x模型

    • 上述模型的缺點:servlet是一個簡單的網路IO模型,當請求進入servlet container時,servlet container就會為其繫結一個執行緒,在併發不高的場景下,這種模型是適用的,但是一旦高併發(比如抽風用jemeter壓測),執行緒數量就會上漲,而執行緒資源是昂貴的(上下文切換,記憶體消耗大)嚴重影響請求的處理時間。在一些簡單業務場景下,不希望為每個request分配一個執行緒,只需要1個或幾個執行緒就能應對極大併發的請求,這種業務場景下servlet模型沒有優勢,所以Zuul 1.x是基於servlet之上的一個阻塞式處理模型,即spring實現了處理所有請求的一個servlet(DispatcherServlet)並由該servlet阻塞式處理模型
  • Gateway模型

    • webFlux:傳統的Web框架,比如說:struts2、springmvc等都是基於Servlet API與Servlet容器基礎之上執行的

      但是在Servlet3.1之後有了非同步非阻塞的支援。而WebFlux是一個典型非阻塞非同步的框架,它的核心是基於Reactor的相關API實現的。相對於傳統的微博框架來說,它可以執行在諸如Netty,Undertow以及支援Servlet3.1的容器上。非阻塞式+函數語言程式設計(Spring5必須讓你使用Java8)

      Spring WebFlux是spring5.0引入的新的響應式框架,區別於Spring MVC,它不需要依賴Servlet API,它是完全非同步非阻塞的且基於Reactor來實現響應式流規範

三大核心概念
  • Route(路由):路由是構建閘道器的基本模組,它由ID,目標URI,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由

  • Predicate(斷言):參考的是Java8java.util.function.Predicate.。開發人員可以匹配HTTP請求中的所有內容(例如請求頭或請求引數)如果請求與斷言相匹配則進行路由

  • Filter(過濾器):指的是Spring框架中GatewayFilter的例項,使用過濾器,可以在請求被路由之前或者之後對請求映象修改

  • 總體

    web請求,通過一些匹配條件,定位到真正的服務節點。並在這個轉發過程的前後,進行一些精細化控制。perdicate就是我們的匹配條件。而Filter就可以理解為一個無所不能的攔截器,有了這兩個元素,再加上目標uri,就可以實現一個具體的路由了。

Gateway工作流程
  • Gateway流程:客戶端向Spring Cloud Gateway發出請求。然後在Gateway Handler Mapping 中找到與請求相匹配的路由,將其傳送到Gateway Web Handler

    Handler再通過指定的過濾器鏈來將請求傳送到我們實際的服務執行業務邏輯,然後返回

    過濾器之間用虛線分開是因為過濾器可能會在傳送代理請求之前(“pre”)或之後(“post”)執行業務邏輯

    Filter在“pre”型別的過濾器可以做引數校驗、許可權校驗、流量監控、日誌輸出、協議轉換等,在“post”型別的過濾器中可以做響應內容、響應頭的修改,日誌的輸出,流量監控等有非常重要的作用

入門配置
通過微服務名實現動態路由
  • 對比未使用Gateway,提供了統一的對外埠9527

  • 動態路由

    • 預設情況下Gateway會根據註冊中心註冊的服務列表,以註冊中心上微服務名為路徑建立動態路由進行轉發,從而實現動態路由
    • 需要注意的是uri的協議為lb,表示啟用Gateway的負載均衡功能。lb://serviceName是spring cloud gateway在微服務中自動為我們建立的負載均衡uri
    • 測試:http://localhost:9527/payment/lb 看到8001/8002兩個埠切換
Predicate的使用
  • 是什麼

    • 啟動9527專案 檢視控制檯

    • Route Predicate Factories這個是什麼?

    • 常用的Route Predicate

      1. After

      2. Before :同理After

      3. Between:同路After

      4. Cookie

      5. Header

      6. Host

      7. Method

        ​ yml: -Method=GET

      8. Path

      9. Query

      10. 說白了,Predicate就是為了實現一組匹配規則,讓請求過來找到對應的Route進行處理

Filter的使用
  • 是什麼

  • Spring Cloud Gateway 的 Filter

    • 生命週期 兩種
      1. pre
      2. post
    • 種類 兩種
      1. Gateway Filter
      2. Global Filter
  • 常用的Gateway Filter

  • 自定義過濾器

    • 自定義全域性Global Filter
      • 兩個主要介面實現 implements GlobalFilter Ordered
      • 能幹嘛
        • 全域性日誌記錄
        • 統一閘道器鑑權
        • 。。。

++++

服務配置

Spring Cloud config分散式配置中心

概述
  • 分散式系統面臨問題---配置問題

    • 微服務意味著要將單體應用中的業務拆分成一個個子服務,每個服務的粒度相對較小,因此係統中會出現大量的服務。由於每個服務都需要必要的配置資訊才能執行,所以一套集中式的、動態的配置管理設施是必不可少的

      Spring Cloud提供了ConfigServer來解決這個問題,我們每一個微服務自己帶著一個application.yml,上百個配置檔案的管理

  • 是什麼

    • SpringCloud Config為微服務架構中的微服務提供集中化的外部配置支援,配置伺服器為各個不同微服務應用的所有環境提供了一個中心化的外部配置
  • 怎麼玩

    • SpingCloud Config分為服務端和客戶端兩部分
    • 服務端也稱為分散式配置中心它是一個獨立的微服務應用,用來連線配置伺服器併為客戶端提供獲取配置資訊,加密/解密資訊等訪問介面
    • 客戶端則是通過指定的配置中心來管理應用資源,以及與業務相關的配置內容,並在啟動的時候從配置中心獲取載入配置資訊,配置伺服器預設採用git來儲存配置資訊,這樣就有助於對環境配置進行版本管理,並且可以通過git客戶端工具來方便的管理和訪問配置內容
  • 能幹嘛

    • 集中管理配置檔案
    • 不同環境不同配置,動態化的配置更新,分環境部署比如dev/test/prod/beta/release
    • 執行期間動態調整配置,不再需要在每個服務不是的機器上編寫配置檔案,服務迴向配置中心統一拉取配置自己的資訊
    • 當配置發生變動時,服務不需要重啟即可感知到配置的變化並應用新的配置
    • 將配置資訊以REST介面的形式暴露
  • 與GitHub整合配置

    • 由於Spring Cloud Config預設使用Git來儲存配置檔案(也有其他方式,比如支援SVN和本地檔案),但最推薦的還是Git,而且使用的是http/https訪問的形式
  • 官網

Config服務端配置與測試
Config客戶端配置與測試
  • 新建cloud-config-client-3355

  • bootstrap.yml

    • 是什麼:

    • 成功實現了客戶端3355訪問SpringCloud Config3344通過GitHub獲取配置資訊

    • 問題隨時而來,分散式配置的動態重新整理

      • Linux運維修改GitHub上的配置檔案內容做調整
      • 重新整理3344,發現ConfigServer配置中心立刻響應
      • 重新整理3355,發現ConfigServer客戶端沒有任何響應
      • 3355沒有變化除非自己重啟或者重新載入
      • 難道每次運維修改配置檔案,客戶端都需要重啟??噩夢
Config客戶端之動態重新整理(**)
  • 避免每次更新配置都要重啟客戶端微服務3355

  • 動態重新整理

    • yml 暴露監控埠號

    • 新增@RefreshScope 註解

    • 需要運維人員傳送Post請求重新整理3355--->curl -X POST "http://localhost:3355/actuator/refresh"

    • 成功實現了客戶端3355重新整理到最新配置內容,避免了服務的重啟

  • 想想還有什麼問題?---->引出了spring cloud bus訊息匯流排

    • 假如有多個微服務客戶端3355/3366/3377。。。。
    • 每個微服務都要執行一次post請求,手動重新整理?
    • 可否廣播,一次通知,處處生效?
    • 我們想大範圍的自動重新整理

++++

服務匯流排

Spring Cloud Bus訊息匯流排

概述
  • 上一講的加深和擴充,分散式自動重新整理配置功能,SpringCloud Bus和SpringCloud Config使用可以實現配置的動態重新整理
  • 是什麼
    • Bus支援兩種訊息代理:RabbitMQ和Kafka
  • 能幹嘛
  • 為何被稱為匯流排
    • 什麼是匯流排:在微服務架構的系統中,通常會使用輕量級的訊息代理來構建一個共用的訊息主題,並讓系統中的所有微服務例項都連線上來。由於該主題中產生的訊息會被所有例項監聽和消費,所以稱它為訊息匯流排。在總線上的各個例項,都可以方便的廣播一些需要讓其他連線在該主題上的例項都知道的訊息。
    • 基本原理:Config Client例項都監聽MQ中同一個topic(預設是SpringCloud Bus).當一個服務重新整理資料的時候,它會把這個資訊放入到Topic中,這樣其他監聽同一Topic的服務就能得到通知,然後去更新自身的配置。
RabbitMQ環境配置(docker 啟動)
SpringCloud Bus動態重新整理全域性廣播
  • cloud-config-client-3366

  • 設計思想:

    1. 利用訊息匯流排觸發一個客戶端/bus/refresh,而重新整理所有客戶端的配置
    2. 利用訊息匯流排觸發一個服務端ConfigServer的/bus/refresh端點,而重新整理所有客戶端的配置(更加推薦)
  • 第二種設計顯然更加合適,第一種不適合的原因如下:

    • 打破了微服務的職責單一性,因為微服務本身是業務模組,它本不應該承擔配置重新整理的職責
    • 破壞了微服務各個節點的對等性
    • 有一定的侷限性,例如,微服務在遷移時,它的網路地址會常常發生變化,此時如果想要做到自動重新整理,那就回增加更多的修改
  • 示例

    1. 給cloud-config-center-3344配置中心服務端新增訊息匯流排支援
    2. 給cloud-config-client-3355客戶端新增訊息匯流排支援
    3. 給cloud-config-client-3366客戶端新增訊息匯流排支援
    4. 測試 curl -X POST "http://localhost:3344/actuator/bus-refresh"
    5. 一次傳送,處處生效
  • 一次修改,廣播通知,處處生效

SpringCloud Bus動態重新整理定點通知
  • 不想全部通知,只想定點通知

  • 一句話:指定具體某一個例項生效而不是全部

    • 公式:http://localhost:配置中心的埠號/actuator/bus-refresh/{destination}
    • /bus/refresh請求不再發送到具體的服務例項上,而是發給config server並通過destination引數類指定需要更新配置的服務或例項
  • 案例:我們這裡以重新整理執行在3355埠上的config-client為例,只通知3355,不通知3366

  • curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"

  • 案例總結

SpringCloud Stream訊息驅動

為什麼要引入SpringCloud Stream
  • 解決什麼痛點
訊息驅動概述
  • 是什麼

  • 設計思想

    • 標準MQ
      • Message:生產者/消費者之間靠訊息媒介傳遞資訊內容
      • 訊息通道MessageChannel:訊息必須走特定的通道
      • 訊息通道MessageChannel的子介面SubscribableChannel,由MessageHandler訊息處理器訂閱:訊息通道里的訊息如何被消費呢,誰負責收發處理
    • 為什麼用Cloud Stream
      • Stream憑什麼可以統一底層差異
        • 通過定義繫結器Binder作為中間層,實現了應用程式與訊息中介軟體細節之間的隔離
      • Binder
        • INPUT對應於消費者
        • OUTPUT對應於生產者
    • Stream中的訊息通訊方式遵循了釋出-訂閱模式
      • Topic主題進行廣播
        • 在RabbitMQ中就是Exchange
        • 在Kakfa中就是Topic
  • Spring Cloud Stream標準流程套路

    • Binder:很方便的連線中介軟體,遮蔽差異
    • Channel:通道,是佇列Queue的一種抽象,在訊息通訊系統中就是實現儲存和轉發的媒介,通過Channel對佇列進行配置
    • Source和Sink:簡單的可理解為參照物件是Spring Cloud Stream自身,從Stream釋出訊息就是輸出,接受訊息就是輸入
  • 編碼API和常用註解

案例說明
  • RabbitMQ環境已經OK
  • 三個子模組
    • cloud-stream-rabbitmq-provider8801,作為生產者傳送訊息模組
    • cloud-stream-rabbitmq-consumer8802,作為訊息接收模組
    • cloud-stream-rabbitmq-consumer8803 作為訊息接收模組
訊息驅動之生產者
  • cloud-stream-rabbitmq-provider8801

訊息驅動之消費者
  • cloud-stream-rabbitmq-consumer8802
分組消費(避免重複消費)與持久化
  • 依照8802,clone一份8803,cloud-stream-rabbitmq-consumer8803
  • 8001生產訊息,8002和8003消費
  • 存在兩個問題:
    • 重複消費
      • 解決方案:分組和持久化屬性group(**)
      • 生產實際案例:
      • 不同的組是可以全面消費的(重複消費);同一組內會發生競爭關係,只有其中一個可以消費
    • 分組
      • 原理:微服務應用放置於同一個group中,就能保證訊息只會被其中一個應用消費一次。不同的組是可以完全消費的,同一個組內會發生競爭關係,只有其中一個可以消費
      • 預設生成流水號,處於不同組,導致重複消費
      • 8802/8803實現了輪詢分組,每次只有一個消費者 8801模組的發的訊息只能被8802或8803其中一個接收到,這樣避免了重複消費-
      • 8802/8803都變成相同組,兩個group相同,同一個組的多個微服務例項,每次只會被一個例項消費
    • 訊息持久化
      • 加上group屬性 預設持久化
      • 去掉group屬性,取消了持久化

SpringCloud Sleuth 分散式請求鏈路跟蹤

概述
  • 為什麼會出現這個技術?需要解決哪些問題?
  • 是什麼
鏈路監控(略)

下篇 SpringCloud Alibaba

SpringCloud Alibaba 入門簡介

為什麼會出現SpringCloud Alibaba
  • Spring Cloud Netflix專案進入維護模式
  • SpringCloud NetFlix Projects Entering Maintenance Mode
    • 什麼是維護模式
SpringCloud Alibaba帶來了什麼
  • 是什麼
  • 能幹嘛
    • 服務限流降級:預設支援 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降級功能的接入,可以在執行時通過控制檯實時修改限流降級規則,還支援檢視限流降級 Metrics 監控
    • 服務註冊與發現:適配Spring Cloud服務註冊與發現標準,預設集成了Ribbon的支援
    • 分散式配置管理:支援分散式系統中的外部化配置,配置更改時自動重新整理
    • 訊息驅動能力:基於Spring Cloud Stream為微服務應用構建訊息驅動能力
    • 分散式事務:使用 @GlobalTransactional 註解, 高效並且對業務零侵入地解決分散式事務問題
    • 阿里雲物件存儲:阿里雲提供的海量、安全、低成本、高可靠的雲端儲存物件。支援在任何應用、任何時間、任何地點儲存和訪問任意型別的資料
    • 分散式任務排程:提供秒級、精準、高可靠、高可用的定時(基於Cron表示式)任務排程服務。同時提供分散式的任務執行模型,如網格任務。網格任務支援海量子任務均勻分配到所有Worker(schedulerx-client)上執行
    • 阿里雲簡訊服務:覆蓋全球的簡訊服務,友好、高效、智慧的互聯化通訊能力,幫助企業迅速搭建客戶觸達通道
  • 元件
    • Sentinel:把流量作為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性
    • Nacos:一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺
    • RocketMQ:一款開源的分散式訊息系統,基於高可用分散式叢集技術、提供低延時的、高可靠的訊息釋出與訂閱服務
    • Dubbo:Apache Dubbo是一款高效能的Java RPC框架
    • Seata:阿里巴巴開源產品,一個易於使用的高效能微服務分散式事務解決方案
    • Alibaba Cloud ACM:一款在分散式架構環境中對應用配置進行集中管理和推送的應用配置中心產品
    • Alibaba Cloud OSS:阿里雲物件儲存服務(Object Storage Service,簡稱OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲端儲存服務。您可以在任何應用、任何時間、任何地點儲存和訪問任意型別的資料
    • Alibaba Cloud ScheduleX:阿里中介軟體團隊開發的一款分散式任務排程產品,提供秒級、精準、高可靠、高可用的定時(基於Cron表示式)任務排程服務
    • Alibaba Cloud SMS:覆蓋全球的簡訊服務,友好、高效、智慧的互聯化通訊能力,幫助企業迅速搭建客戶觸達通道
SpringCloud alibaba學習資料獲取

Spring Cloud Alibaba Nacos服務註冊和配置中心

Nacos簡介
  • 為什麼叫Nacos

    • 前四個字母分別是Naming和Configuration的前兩個字母,最後的s為Service
  • 是什麼

    • 一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺

    • Nacos:Dynamic Naming and Configuration Service

    • Nacos就是註冊中心+配置中心的組合--->Nacos=Eureka + Config + Bus

    • Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元資料及流量管理。

      Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平臺。 Nacos 是構建以“服務”為中心的現代應用架構 (例如微服務正規化、雲原生正規化) 的服務基礎設施。

  • 能幹嘛

    • 替代Eureka做服務註冊中心
    • 替代Config做服務配置中心
  • 去哪下

  • 各種註冊中心比較

安裝並執行Nacos(官網下載)
Nacos作為服務註冊中心演示
  • cloudalibaba-provider-payment9001,cloudalibaba-provider-payment9002

  • cloudalibaba-consumer-nacos-order83

  • 註冊進了Nacos

  • 為什麼nacos支援負載均衡:依賴中整合了ribbon

    • 83訪問9001/9002,輪詢負載OK
各種註冊中心比較
  • Nacos支援CAP中 AP和CP模式的切換

  • Nacos全景圖所示

  • Nacos和CAP

  • Nacos支援AP和CP模式的切換

Nacos作為服務配置中心演示
  • Nacos作為配置中心-基礎配置

    • cloudalibaba-config-nacos-client3377
    • why配置兩個
      • application.yml
      • bootstrap
      • 在Nacos中新增配置資訊
        • 理論:Nacos中的dataid的組成格式與SpringBoot配置檔案中的匹配規則
        • 實操
          • 配置新增
          • Nacos介面配置對應
      • 自帶動態重新整理:修改下Nacos中的yaml配置檔案,再次呼叫檢視配置的介面,就會發現配置已經重新整理
  • Nacos作為配置中心-分類配置

    • 問題:多環境多專案管理

    • Nacos的圖形化管理介面

      • 配置管理

      • 名稱空間

    • Namespace+Group+Data ID三者關係?為什麼這麼設計

    • Case

      • DataID方案

        • 指定spring.profile.active和配置檔案的DataID來使不同環境下讀取不同的配置
        • 預設空間+預設分組+新建dev和test兩個DataID
          • 新建dev配置DataID
          • 新建test配置DataID
        • 通過spring.profile.active屬性就能進行多環境下配置檔案的讀取
      • Group方案

        • 在config下增加一條group的配置即可。可配置為DEV_GROUP或TEST_GROUP

      • Namespace方案

        • 新建dev/test的Namespace
        • 回到服務管理-服務列表檢視
        • 按照域名配置填寫
Nacos叢集和持久化配置(**)
官方說明
Nacos持久化配置解釋
  • Nacos預設自帶的是嵌入式資料庫derby,https://github.com/alibaba/nacos/blob/develop/config/pom.xml

  • derby到MySQL切換配置步驟

    • nacos-server-1.1.4\nacos\conf目錄下找到sql指令碼,執行指令碼nacos-mysql.sql

    • nacos-server-1.1.4\nacos\conf目錄下找到application.properties

      # db mysql
      spring.datasource.platform=mysql
      db.num=1
      db.url.0=jdbc:mysql://127.0.0.1:3306/nacosconfig?serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
      db.user=root
      db.password=123456
      
    • 啟動nacos,可以看到是個全新的空記錄介面,以前是記錄進derby

Linux版Nacos+MySQL生產環境配置
  • 預計1個nginx+3個nacos註冊中心+1個mysql

  • 搭建步驟參考https://www.jianshu.com/p/ad12f28c4e67

  • 叢集配置步驟(**)

  • 測試

    • 微服務cloudalibaba-provider-payment9002啟動註冊進nacos叢集
  • 高可用小總結

SpringCloud Alibaba Sentinel實現熔斷與限流

Sentinel簡介
  • 官網:https://github.com/alibaba/Sentinel/wiki

  • 是什麼

    • Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性
      • 豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、訊息削峰填谷、叢集流量控制、實時熔斷下游不可用應用等
      • 完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級資料,甚至 500 臺以下規模的叢集的彙總執行情況
      • 廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模組,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel
      • 完善的 SPI 擴充套件點:Sentinel 提供簡單易用、完善的 SPI 擴充套件介面。您可以通過實現擴充套件介面來快速地定製邏輯。例如定製規則管理、適配動態資料來源等

  • 能幹嘛

  • 怎麼玩

    • 服務使用中的各種問題
      • 服務雪崩
      • 服務降級
      • 服務熔斷
      • 服務限流
安裝Sentinel控制檯
  • Sentinel元件由兩部分構成
  • 安裝步驟
    • 官網下載,sentinel-dashboard-x.x.jar
    • 執行命令: java -jar sentinel-dashboard-x.x.jar
    • 訪問sentinel管理介面
初始化演示工程
  • cloudalibaba-sentinel-service8401
  • 啟動Nacos8848成功
  • 啟動Sentinel8080
  • 啟動8401微服務後檢視sentienl控制檯
    • 第一次訪問,空白頁
    • Sentinel採用的懶載入說明,執行一次訪問即可
    • 效果圖:
流控規則
  • 基本介紹

    • 進一步介紹

  • 流控模式

    • 直接(預設)

      • 系統預設,直接->快速失敗

      • 配置及說明

      • 測試

        • 快速點選訪問http://localhost:8401/testA
        • 結果;Blocked by Sentinel (flow limiting)
        • 思考:是否應該加一個類似fallback的兜底方法?
    • 關聯

      • 是什麼

        • 當關聯的資源達到閾值時,就限流自己
        • 當與A關聯的資源B達到閾值後,就限流自己
        • B惹事,A掛了
        • 應用場景: 比如支付介面達到閾值,就要限流下訂單的介面,防止一直有訂單
      • postman模擬併發密集訪問testB

        • 配置規則

        • postman裡新建多執行緒集合組

        • 將訪問地址新增進新執行緒組 -- save as 選擇對應的collection

        • 大批量執行緒高併發訪問B,導致A失效了

    • 鏈路

      • 鏈路流控模式指的是,當從某個介面過來的資源達到限流條件時,開啟限流;它的功能有點類似於針對 來源配置項,區別在於:針對來源是針對上級微服務,而鏈路流控是針對上級介面,也就是說它的粒度 更細
  • 流控效果

    • 直接--->快速失敗(預設的流控處理),直接失敗,丟擲異常

    • 預熱

      • 說明:公式:閾值除以coldFactor(預設值為3),經過預熱時長後才會達到閾值

      • 官網:

      • 預設coldFactor為3,即請求QPS從threshold(閾值)/3開始,經預熱時長逐漸升至設定的QPS閾值。

      • 限流冷啟動:https://github.com/alibaba/Sentinel/wiki/限流---冷啟動

      • 原始碼

      • 配置

      • 測試:多次點選http://localhost:8401/testB 結果:剛開始不行,後續慢慢OK

      • 應用場景

    • 排隊等待

      • 勻速排隊,閾值必須設定為QPS

      • 官網

降級規則
  • 官網(https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7)

  • 基本介紹

    • 進一步說明

    • Sentinel的斷路器是沒有半開狀態的

      • 半開的狀態系統自動去檢測是否請求有異常,沒有異常就關閉斷路器恢復使用,有異常則繼續開啟斷路器不可用。具體可以參考Hystrix
      • hystrix
  • 降級策略實戰

    • RT:平均響應時間

      • 是什麼
      • jmeter壓測--->1秒鐘打入10個請求
      • 結論
    • 異常比例

      • 是什麼

      • 配置

      • jmeter壓測,結論

    • 異常數

      • 是什麼

      • 異常數是按照分鐘統計的

      • 配置+測試

熱點key限流(**)
  • 基本介紹

  • 官網:https://github.com/alibaba/Sentinel/wiki/熱點引數限流

  • 承上啟下複習start

  • @SentinelResource等同於@HystrixCommand

  • 原始碼:com.alibaba.csp.sentinel.slots.block.BlockException

  • 配置

    • @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    • 不新增blockHandler方法,會把異常打到前臺頁面,提示不友好
    • 方法testHostKey裡面第一個引數只要QPS超過每秒1次,馬上降級處理,並且用了我們自己定義的降級提示
  • 引數例外項

    • 上述案例演示了第一個引數p1,當QPS超過1秒1次點選後馬上被限流

    • 特殊情況:

      • 普通:超過1秒鐘一個後,達到閾值1後馬上被限流

      • 特例:我們期望p1引數當它是某個特殊值時,它的限流值和平時不一樣.

        例如當p1的值等於5時,它的閾值可以達到200

    • 配置

  • 測試結果:

    • 當p1等於5的時候,閾值變為200
    • 當p1不等於5的時候,閾值就是平常的1
  • 前提:熱點引數的注意點,引數必須是基本型別或者String

  • 其他:存在異常

系統規則
@SentinelResource
  • 按資源名稱限流+後續處理

    • 啟動Nacos成功

    • 啟動Sentinel成功

    • 修改cloudalibaba-sentinel-service8401

    • 業務類RateLimitController

    • 配置

      表示1秒鐘內查詢次數大於1,就跑到我們自定義的處流,限流

    • 測試結果:1秒鐘點選1下,OK

      超過上述問題,瘋狂點選,返回了自己定義的限流處理資訊,限流傳送--->進入blockHandler配置的方法

    • 額外問題:此時關閉微服務8401看看,Sentinel控制檯,流控規則消失了,臨時/持久

  • 按照URL地址限流+後續處理

    • 通過訪問的URL來限流,會返回Sentinel自帶預設的限流處理資訊
    • 業務類RateLimitController
    • 配置
    • 測試結果
  • 上面兜底方案面臨的問題

  • 客戶自定義限流處理邏輯

    • 建立customerBlockHandler類用於自定義限流處理邏輯
    • 自定義限流處理類
    • 業務類指定處理方法
    • 測試結果:業務與異常處理結構,blockHandlerClass指定異常處理類和blockHandler指定該類中具體處理方法
  • 更多註解屬性說明

    • 注意

    • Sentinel主要有三個核心API

      1. SphU定義資源
      2. Tracer定義統計
      3. ContextUtil定義了上下文
服務熔斷功能
sentinel整合ribbon+openFeign+fallback(**)
Ribbon系列
  • 啟動nacos和sentinel

  • 提供者9003/9004

  • 消費者84

  • 只配置fallback,處理執行時異常

  • 只配置blockHandler,blockHandler只負責sentinel控制檯配置違規

  • fallback和blockHandler都配置

  • 忽略屬性 exceptionToIgnore

Feign系列
* 修改84模組,Fegin元件一般是在消費側
* yml 新增 feign配置
* 主啟動新增@EnableFeignClients啟動Feign的功能
* 業務類![image-20200723155057366](https://img2020.cnblogs.com/blog/1875400/202008/1875400-20200819125811650-2022437251.png)
* 測試84呼叫9003/9004,此時故意關閉9003和9004微服務提供者,**84消費自動降級**,不會被耗死
熔斷框架比較
規則持久化
  • 是什麼:一旦我們重啟應用,Sentinel規則將消失,生產環境需要將配置規則進行持久化

  • 怎麼玩:將限流配置規則持久化進Nacos儲存,只要重新整理8401某個rest地址,sentinel控制檯的流控規則就能看到,只要Nacos裡面的配置不刪除,針對8401上Sentinel上的流控規則持續有效

  • 步驟

    • 修改cloudalibaba-sentinel-service8401

    • yml :新增資料來源配置

        cloud:
          nacos:
            discovery:
              #Nacos服務註冊中心地址
              server-addr: localhost:8848
          sentinel:
            transport:
              #配置Sentinel dashboard地址
              dashboard: localhost:8080
              port: 8719  #預設8719,假如被佔用了會自動從8719開始依次+1掃描。直至找到未被佔用的埠
            datasource:
              ds1:
                nacos:
                  server-addr: localhost:8848
                  dataId: cloudalibaba-sentinel-service
                  groupId: DEFAULT_GROUP
                  data-type: json
                  rule-type: flow
      
      
    • 新增Nacos業務規則配置

      [
          {
               "resource": "/rateLimit/byUrl",
               "limitApp": "default",
               "grade":   1,
               "count":   1,
               "strategy": 0,
               "controlBehavior": 0,
               "clusterMode": false    
          }
      ]
      

    • 啟動8401後重新整理sentinel發現業務規則有了

    • 重新啟動8401再看sentinel,多次呼叫,流控配置重新出現了,持久化驗證通過

SpringCloud Alibaba Seata處理分散式事務

分散式事務問題
  • 分散式前

    • 單機單庫沒這個問題
    • 1:1 -> 1:N -> N: N
  • 分散式之後

  • 一句話:一次業務操作需要跨多個數據源或需要跨多個系統進行遠端呼叫,就會產生分散式事務問題

Seata簡介
  • 是什麼

    • Seata是一款開源的分散式事務解決方案,致力於在微服務架構下提供高效能和簡單易用的分散式事務服務
    • 官網:http://seata.io/zh-cn/
  • 能幹嘛

    • 一個典型的分散式事務過程:

      • 分散式事務處理過程一個ID+三元件模型

        • Transaction ID XID 全域性唯一的事務ID
        • 三元件:
          1. Transaction Coordinator(TC):事務協調器,維護全域性事務的執行狀態,負責協調並驅動全域性事務的提交或回滾;
          2. Transaction Manager(TM) :控制全域性事務的邊界,負責開啟一個全域性事務,並最終發起全域性提交或全域性回滾的決議;
          3. Resource Manager(RM) :控制分支事務,負責分支註冊,狀態彙報,並接收事務協調器的指令,驅動分支(本地)事務的提交和回滾;
      • 處理過程

  • 去哪下:釋出說明:https://github.com/seata/seata/releases

  • 怎麼玩

    • Spring 本地@Transactional
    • 全域性@GlobalTransactional
Seata-Server安裝
  • 官網下載穩定版本:https://github.com/seata/seata/releases
  • 解壓到指定目錄並修改conf目錄下的file.conf配置檔案
    • 先備份原始file.conf檔案
    • 主要修改:自定義事務組名稱+事務日誌儲存模式為db+資料庫連線資訊
    • file.conf,主要修改service模組和store模組兩個模組
    • 在seata庫裡建表
    • 修改\conf目錄下的registry.conf配置檔案,將seata註冊進nacos
    • 先啟動Nacos埠號8848
    • 再啟動seata-server
訂單/庫存/賬戶業務資料庫準備
  • 以下演示都需要先啟動Nacos後啟動Seata,保證兩個都OK

  • 分散式事務業務說明:三個服務 訂單服務、庫存服務、賬戶服務。當用戶下單時,會在訂單服務中建立一個訂單,然後通過遠端呼叫庫存服務來扣減下單商品的庫存,再通過遠端呼叫賬戶服務來扣減使用者賬戶裡面的餘額,最後在訂單服務中修改訂單狀態為已完成

    該操作跨越三個資料庫,有兩次遠端呼叫,很明顯會有分散式事務問題

    下訂單-->扣庫存-->減賬戶(餘額)

  • 建立業務資料庫

    -- seata_order: 儲存訂單的資料庫
    CREATE DATABASE seata_order;
    
     -- seata_storage:儲存庫存的資料庫
    CREATE DATABASE seata_storage;
     
     -- sseata_account: 儲存賬戶資訊的資料庫
    CREATE DATABASE seata_account;
    
  • 按照上述3庫分別建對應業務表

    • seata_order庫下建t_order表

      CREATE TABLE t_order(
          `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
          `user_id` BIGINT(11) DEFAULT NULL COMMENT '使用者id',
          `product_id` BIGINT(11) DEFAULT NULL COMMENT '產品id',
          `count` INT(11) DEFAULT NULL COMMENT '數量',
          `money` DECIMAL(11,0) DEFAULT NULL COMMENT '金額',
          `status` INT(1) DEFAULT NULL COMMENT '訂單狀態:0:建立中; 1:已完結'
      ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
       
      SELECT * FROM t_order;
      
    • seata_storage庫下建t_storage表

      CREATE TABLE t_storage(
          `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
          `product_id` BIGINT(11) DEFAULT NULL COMMENT '產品id',
         `'total` INT(11) DEFAULT NULL COMMENT '總庫存',
          `used` INT(11) DEFAULT NULL COMMENT '已用庫存',
          `residue` INT(11) DEFAULT NULL COMMENT '剩餘庫存'
      ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
       
      INSERT INTO seata_storage.t_storage(`id`,`product_id`,`total`,`used`,`residue`)
      VALUES('1','1','100','0','100');
       
       
      SELECT * FROM t_storage;
      
    • seata_account庫下建t_account表

      CREATE TABLE t_account(
          `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',
          `user_id` BIGINT(11) DEFAULT NULL COMMENT '使用者id',
          `total` DECIMAL(10,0) DEFAULT NULL COMMENT '總額度',
          `used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用餘額',
          `residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩餘可用額度'
      ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
       
      INSERT INTO seata_account.t_account(`id`,`user_id`,`total`,`used`,`residue`) VALUES('1','1','1000','0','1000')
       
      SELECT * FROM t_account;
      
    • 按照上述3庫分別建對應的回滾日誌表

      • 訂單-庫存-賬戶3個庫下都需要建各自的回滾日誌表

      • drop table `undo_log`;
        CREATE TABLE `undo_log` (
          `id` bigint(20) NOT NULL AUTO_INCREMENT,
          `branch_id` bigint(20) NOT NULL,
          `xid` varchar(100) NOT NULL,
          `context` varchar(128) NOT NULL,
          `rollback_info` longblob NOT NULL,
          `log_status` int(11) NOT NULL,
          `log_created` datetime NOT NULL,
          `log_modified` datetime NOT NULL,
          `ext` varchar(100) DEFAULT NULL,
          PRIMARY KEY (`id`),
          UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
        ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
        
訂單/庫存/賬戶業務微服務準備
Test
  • 下訂單->減庫存->扣餘額->改(訂單)狀態
  • 資料庫初始情況
  • 正常下單
  • 超時異常,沒加@GlobalTransactional
    • AccountServiceImpl新增超時
    • 故障情況:當庫存和賬戶餘額扣減後,訂單狀態並沒有設定為已經完成,沒有從零改為1。而且由於feign的重試機制,賬戶餘額還有可能被多次扣減
  • 超時異常,新增@GlobalTransactional
    • AccountServiceImpl新增超時
    • OrderServiceImpl@GlobalTransactional
    • 下單後資料庫資料並沒有任何改變,記錄都新增不進來
Seata原理
  • 再看TC/TM/RM三大元件

    • 分散式事務執行流程(**)
      • TM開啟分散式事務(TM向TC註冊全域性事務記錄)
      • 換業務場景,編排資料庫,服務等事務內資源(RM向TC彙報資源準備狀態)
      • TM結束分散式事務,事務一階段結束(TM通知TC提交/回滾分散式事務)
      • TC彙總事務資訊,決定分散式事務是提交還是回滾
      • TC通知所有RM提交/回滾資源,事務二階段結束。
  • AT模式如何做到對業務的無侵入

    • 是什麼

    • 一階段載入

    • 二階段提交

    • 二階段回滾

  • debug:觀察資料庫回滾細節

  • 總結