Sentinel簡單使用(1)

xxxLin發表於2024-10-21

使用場景

在微服務架構中,服務之間會進行大量的呼叫。為了防止某個服務被過多的請求壓垮,導致整個系統崩潰,就需要對流量進行控制。同時,當某個服務出現故障時,為了防止故障擴散到整個系統,需要進行熔斷操作。Sentinel提供了流量控制和熔斷降級的功能,因此非常適合在這種場景下使用。

雪崩效應

在微服務系統架構中,服務間呼叫關係錯綜複雜,一個微服務往往依賴於多個其它微服務。一個服務的不可用導致整個系統的不可用的現象就被稱之為雪崩效應。

解決方法

  1. 超時處理
    在設定兩個或多個微服務之間相互訪問的時候,我使用的是OpenFeign來實現的訪問,OpenFeign中可以自定義配置,日誌配置、超時配置、重試配置
  2. 隔離處理https://www.jindouyun.cn/document/industry/details/184685#_293
  3. 熔斷處理https://www.jindouyun.cn/document/industry/details/184685#_293
  4. 流量控制
    本篇文章主要學習的是如何使用流量控制來處理請求過多導致微服務伺服器崩潰

流量控制使用的是Sentinel元件來實現需求

Sentinel前言配置

1.下載
在官網下載Sentinel控制器https://github.com/alibaba/Sentinel/releases
下載完成後可以在下載目錄中找到一個Jar包,那就是我們啟動sentinel所需要的資源
2.啟動
java -jar +目錄下的jar包
如果需要更改預設埠,賬號,密碼,可以透過以下配置

配置項 預設值 說明
server.port 8080 服務埠
sentinel.dashboard.auth.username sentinel 預設使用者名稱
sentinel.dashboard.auth.password sentinel 預設密碼

注意需要在每一個配置項前面新增(-D)
例如:修改埠號java -Dserver.port=8090 -jar sentinel-dashboard-2.0.0-alpha-preview.jar
3.訪問Sentinel頁面
訪問http://localhost:8080頁面,就可以看到sentinel的控制檯了:

如何在IDEA中整合Sentinel

1.匯入依賴

<!--sentinel的依賴-->
<dependency>
    <groupId>com.alibaba.cloud</groupId> 
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2.在IDEA的yaml或者yml檔案中匯入相關的配置

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # 配置sentinel控制檯地址

3.訪問任意一個控制層的介面,就可以觸發sentinel的監控

使用Sentinel流量控制(當系統面臨高併發請求時,防止系統過載....)

Sentinel是在上述四種處理方法中唯一一個提前預防來處理問題的

首先我們先了解流量控制中的相關概念
1.簇點鏈路
當請求進入微服務時,首先會訪問DispatcherServlet,然後進入Controller、Service、Mapper,這樣的一個呼叫鏈就叫做簇點鏈路
2.資源
簇點鏈路中每一個被監控的Controller介面就是一個資源-->流控、熔斷等都是針對簇點鏈路中的資源來設定的

  • 流控: 流量控制
  • 降級:降級熔斷
  • 熱點:熱點引數限流,是限流的一種
  • 授權:請求的許可權控制

sentinel快速入門

1.建立一個控制層在,其中編寫Controller

    @GetMapping("/findUserByUserId/{userId}")
    public User findUserByUserId(@PathVariable("userId") Long userId) {
        return userService.findUserByUserId(userId);
    
    }
  順便補齊後續的Server和Mapper,還有根據使用者Id查詢使用者資訊的SQL語句
  記得配置前面的依賴和配置

2.在瀏覽器訪問ConTroller資源路徑後,就可以在sentinel控制中心看到對應的請求

我們可以點選後面的流控來進行操作

  • 單機閾值:每秒最大能接收的請求數量
    為了模擬併發請求這裡我們需要使用一個工具(jmeter測試工具)

    這裡設定好執行緒數和時間,然後啟動,我們就能看到相對應的效果

    上述圖片中執行緒數是我們需要傳送的請求數量,時間是我們需要執行的時間,所以每秒傳送的請求數量是10,但是我們設定的單機閾值是5,所以會出現前五個請求成功,後五個請求失敗的效果
    注意:如果測試結果不是上述情況,那是因為sentinel在統計請求的時候,把一部分的請求統計到了下一秒中導致的。

sentinel中三種詳細的模式使用及介紹

  1. 直接:統計當前資源的請求,觸發閾值時對當前資源直接限流,也是預設的模式
  2. 關聯:統計與當前資源相關的另一個資源,觸發閾值時,對當前資源限流
  3. 鏈路:統計從指定鏈路訪問到本資源的請求,觸發閾值時,對指定鏈路限流

直接模式

就是我們上面的快速入門案例

關聯模式

統計與當前資源相關的另一個資源,觸發閾值時,對當前資源限流
配置方式:

1.基於上面的Controller我們需要再一次建立一個請求以便實現我們的功能

    @GetMapping("/UpdataUserById")
    public String UpdataUserById(){
        return "修改使用者資料成功";
    }

2.重啟服務,在瀏覽器傳送對應的的請求,讓其產生簇點鏈路

3.配置流控規則,當/api/user/updateUserById資源被訪問的QPS超過5時,對/api/user/findUserByUserId/1請求限流。對哪個端點限流,就點選哪個端點後面的按鈕。我們是對使用者查詢/api/user/findUserByUserId/1限流,因此點選它後面的按鈕:

4.在Jmeter中進行測試

鏈路模式

只針對從指定鏈路訪問到本資源的請求做統計,判斷是否超過閾值,如果超過閾值對從該鏈路請求進行限流。
配置方法:
如果只希望統計從/api/user/query進入到users的請求,並進行限流操作,則可以這樣配置:

2.案例實現

  • 在UserService中新增一個queryUsers方法,不用實現業務
  public void queryUsers(){
    System.err.println("查詢使用者");
}
  • 在上述Controller中,新增兩個端點(請求方法),在這兩個端點中分別呼叫UserService中的queryUsers方法
    @GetMapping(value = "/save")
    public String save() {
        userService.queryUsers();
        System.out.println("儲存使用者");
        return "訂單儲存成功" ;
    }

    @GetMapping(value = "/query")
    public String query() {
        userService.queryUsers();
        System.out.println("查詢使用者");
        return "查詢使用者成功" ;
    }
  • 透過@SentinelResource標記UserService中的queryUsers方法為一個sentinel監控的資源(預設情況下,sentinel只監控controller方法)
@SentinelResource("users")
public void queryUsers(){
    System.err.println("查詢使用者");
}
  • 更改application.yml檔案中的sentinel配置
    鏈路模式中,是對不同來源的兩個鏈路做監控。但是sentinel預設會給進入spring mvc的所有請求設定同一個root資源,會導致鏈路模式失效。因此需要關閉這種資源整合。
spring:
  cloud:
    sentinel:
      web-context-unify: false # 關閉context整合
  • 重啟服務,訪問/api/user/save和/api/user/query,可以檢視到sentinel的簇點鏈路規則中,出現了新的資源
  • 新增流控規則,點選users資源後面的流控按鈕,在彈出的表單中填寫下面資訊:

    只統計從/api/user/query進入/users的資源,QPS閾值為2,超出則被限流。
  • jmeter測試
    選擇《流控模式-鏈路》

    可以看到這裡200個執行緒,50秒內發完,QPS為4,超過了我們設定的閾值2。
    一個http請求是訪問/api/user/save

    另一個是訪問/api/user/query

    執行測試,察看結果樹:
    訪問/api/user/save,沒有進行限流

    訪問/api/user/query,進行限流了

流控效果

  1. 快速失敗:達到閾值後,新的請求會被立即拒絕並丟擲FlowException異常,是預設的處理方式
  2. warm up:預熱模式,對超出閾值的請求同樣是拒絕並丟擲異常,但這種模式閾值會動態變化,從一個較小值逐漸增加到最大閾值
  3. 排隊等待:讓所有的請求按照先後次序進入到一個佇列中進行排隊,當某一個請求最大的預期等待時間超過了所設定的超時時間時同樣是拒絕並丟擲異常

warm up

  • 閾值(QPS):是一個微服務一秒能夠承受的最大的請求數
  • 冷啟動:剛啟動一個伺服器的時候,一切資源尚未啟動
  • 如果直接將QPS跑到最大,可能導致伺服器當機
    Warm Up 也叫做預熱模式,個人理解是閾值是一個動態的,會從一個較小值逐漸增加到最大閾值。

WarmUp案例:

測試的是上述Controller的/api/user/findUserByUserId/1

  • 設定最大閾值10,預熱時間5秒
  • 在測試工具中設定執行緒數200,時間20秒->每秒10個請求
    得出的結果是由最剛開始的三個成功請求,隨著時間的推移閾值會變大,成功的請求也會變多,直到最大閾值10
    image image

排隊等待
解釋:假設我現在有最大閾值10,第一秒我處理了10個請求,但是我每秒接收的請求是15,那麼多出來的5個請求就會存放在佇列中等待,第二秒我會優先處理上一次在佇列中的請求,那麼這一次我的佇列中就存在10個請求...依次類推
當某一個請求在佇列中等待的時間超過了設定的超時時間,那麼這個請求同樣是拒絕並丟擲異常

那麼等待的時間如何計算呢?

假如最大閾值為5,就是一秒處理5個請求,1/5=0.2/s 每200ms處理一個請求,設定超時時間=2000ms,那麼就是等待時間超過了2000ms的請求就會被拒絕
比如現在有12個請求
那麼第六個請求的預期等待時間=200ms(6-1)=1000ms
第十二個的請求的預期等待時間=200ms
(12-1)=2200ms,那麼第十二個請求就會被拒絕

排隊等待案例:

1.給/api/user/findUserByUserId/{userId}這個資源設定限流,最大QPS為10,利用排隊的流控效果,超時時長設定為5s
2.在測試工具中設定執行緒數300,時間為20,那麼每秒傳送的請求為15個,QPS=15超過了我們設定的10,
3.結果等待時間長的將會被拒絕
image
4.在sentinel的監控中實時監控的QPS曲線
image

熱點引數限流

使用場景

雙十一的情境下,某些特價商品訪問量非常大,但是一些普通的商品訪問量比較正常,那麼我們可以根據,傳送的請求中的引數來設定熱點限流,熱點指的是訪問量多的商品

熱點引數限流:
統計請求中引數相同的情況,判斷是否超過了閾值,超過了閾值就限流
image

熱點引數限流實現

1.需要在所屬的Controller的請求方法上新增註解
@SentinelResource("hot") 括號內填寫上面名字都行,但是要對應編輯熱點規則的資源名
2.配置sentinel

  • 在熱點規則中新增新的熱點規則
    image
這是當id=1的情況,不是熱點程式碼每秒只能執行2個請求 這是當id=2的情況,是熱點程式碼每秒只能執行5個請求 這是當id=3的情況,是熱點程式碼每秒只能執行10個請求
image image image

相關文章