聊聊Sentinel流量控制

2023.10.09

聊聊Sentinel流量控制


雪崩問題雖然有四種方案(流量控制、熔斷降級、線程隔離、超時處理),流量控制是避免服務因突發的流量而發生故障,是對微服務雪崩問題的預防,所以我們先學習Sentinel的流量控製或說是限流。

今日目標

  • 安裝Sentinel
  • 專案整合Sentinel

1.流量控制

雪崩問題雖然有四種方案(流量控制、熔斷降級、線程隔離、超時處理),流量控制是避免服務因突發的流量而發生故障,是對微服務雪崩問題的預防,所以我們先學習Sentinel的流量控製或說是限流。

Sentinel如何做到流量控制?

Sentinel監控SpringMVC的每一個端點(Endpoint),因此SpringMVC的每一個端點(Endpoint)就是呼叫連結中的一個資源。請求進入微服務時,存取DispatcherServlet,然後進入Controller、Service、Mapper,這樣的一個呼叫鏈就叫做簇點連結。簇點連結中被監控的每一個介面就是一個資源。

例如,我們剛剛造訪的order-service中的OrderController中的端點:/order/{Id}

圖片圖片

後續我們的流控、熔斷都會針對簇點連結中的資源進行發起,因此我們可以點擊對應資源後面的按鈕來設定規則:

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

2.快速上手

點選編輯資源/order/{id} 的流控按鈕

圖片圖片

表單中可以填寫限流規則,如下:

圖片圖片

填入單機閾值:2,其意義為:限制資源/order/{id} 的QPS為2,表示每秒只允許2次請求,超過的請求會被攔截並報錯。

2.1.測試

快速刷新瀏覽器時,會發現出現下述錯誤訊息

圖片圖片

但一般來說生產的流量要更多,這裡我們將藉助一個壓測工具:Jmeter做更全面的壓力測試

2.2. 利用Jmeter測試

下載

可Apache Jmeter官網下載,網址:https://jmeter.apache.org/

圖片圖片

解壓縮

Jmeter下載下來之後,解壓縮即可使用,目錄結構如下:

圖片圖片

其中的bin目錄就是執行的腳本,其中包含啟動腳本:

圖片圖片

運行

雙擊jmeter.bat即可運作:

圖片圖片

Jmeter測試

使用Jmeter測試QPS < 2

圖片圖片

此規則如下:10個請求在1s內執行完成,此時生效的限流規則上面我們配置的為2(每秒最多2個請求通過)

圖片圖片

啟動

圖片圖片

運行啟動後會發現每秒能通過的請求最多2個(如下展示可能會亂序,以請求時間為準):

圖片圖片

此時,我們就完成了流量控制的入門效果,這效果也是流控模式之一的直接模式。

如果您覺得本文不錯,歡迎關注,按讚,收藏支持,您的關注是我堅持的動力!

3. Sentinel流控模式

Sentinel新增限流規則時,點選進階選項,可選擇三種串流模式:

  • 直接:統計目前資源的請求,觸發閾值時對目前資源直接限流,也是預設的模式
  • 關聯:統計與目前資源相關的另一個資源,觸發閾值時,對當前資源限流
  • 連結:統計從指定連結存取到本資源的請求,觸發閾值時,對指定連結限流

圖片圖片

快速入門就是直接模式,也是預設方式

3.1 Sentinel流控-直接模式

什麼是Sentinel串流直接模式

直接模式:針對目前資源的請求,觸發閾值時就對目前資源直接限流,也是預設的模式。

直接模式適用場景

對於沒有明顯差異、特殊化場景的都可以採用直接模式,它更簡單易用

3.2 Sentinel流控-關聯模式

什麼是關聯模式

關聯模式:統計與目前資源相關的另一個資源,觸發閾值時,對目前資源限流

關聯模式適用場景

在一個商城系統中,用戶付款時需要修改訂單狀態,同時用戶需要查詢訂單。查詢和修改操作會爭搶資料庫鎖定(讀速過高影響寫、寫速過高影響讀取速度),爭搶本身帶來的開銷會降低整體吞吐量。此時我們需要優先保證修改訂單的功能,對查詢對單業務限流。即當A觸發條件時,被關聯的資源B產生限流。

圖片圖片

關聯模式實現關聯規則建立如下:

圖片圖片

規則解釋

當存取/write介面次數超過閾值(我們對/write寫有自己的流控規則),就會對/read介面進行限流,從而避免對:/write資源的影響

關聯規則實戰

需求

  • 在OrderController中新建兩個端點(http介面):/order/query 和/order/update
  • 設定關聯流控規則:當/update介面存取超過QPS>3時,對/query進行限流

【步驟一】:定義/order/query接口

@GetMapping("/query")
public String queryOrder() {
    return "查询order成功";
}
  • 1.
  • 2.
  • 3.
  • 4.

【步驟二】:定義/order/update接口

@GetMapping("/update")
public String updateOrder() {
    return "更新order成功";
}
  • 1.
  • 2.
  • 3.
  • 4.

【步驟三】 重啟服務,查看sentinel控制台的簇點鏈路

重新啟動SentinelOrderApplication服務後,瀏覽器存取端點:http://localhost:9092/order/query、http://localhost:9092/order/update,造訪Sentinel控制台,檢視到新的端點資訊:

圖片圖片

【步驟四】 設定關聯流控規則

例子是對/order/query介面進行限流,那麼就點擊其後面對應按鈕。

圖片圖片

配置流程控規則如下:

注意:我們是針對誰做限流,就點擊對應資源的流控按鈕,這裡我們針對:/order/query

圖片圖片

【步驟五】 Jemter測試配置關聯流控

Jmeter壓測驗證,持續時長10s,qps=10,目的是持續造成超過配置閾值的視窗期,給予使用者驗證的時間

可以看到100個用戶,10秒,因此QPS為10,超過了我們設定的閾值:3

查看HTTP請求

圖片圖片

請求的目標是/order/update,這樣端點/order/update就會觸發閾值。

注意:限流的目標是/order/query,我們在瀏覽器訪問,可以發現:

圖片圖片

3.3. Sentinel流控-鏈路模式

什麼是鏈路模式

連結模式:針對從指定連結存取到本資源的請求做統計,判斷是否超過閾值

鏈路模式適用場景

身為業務開發人員,我們有訂單查詢業務,同時輸出做頁面展現,存取連結:自身系統Controller-->查詢訂單介面。此時資料團隊需要依賴我們的介面做駕駛艙信息,因為我們將查詢訂單介面暴露給別的團隊,即新增一條存取連結:資料團隊Controller-->查詢訂單介面。自身系統的QPS我們根據壓測做過合理評估,但是數據團隊的請求我們並未考慮,假設有上萬的請求過來,我們自身的系統效能也會收到明顯影響。此時我們就需要將來自資料團隊的呼叫加上限流。如下

圖片圖片

鏈路模式實作例如有兩個請求鏈路:

  • /user --> /userinfo
  • /login --> /userinfo

如果只希望統計從/login進入/userinfo請求,則可以這樣配置:

圖片圖片

鏈路規則實戰

需求

有查詢訂單(/query)和建立訂單(/createOrder)業務,兩者都需要查詢商品(service層方法queryGoods)。針對從查詢訂單進入查詢商品的請求統計,並設定限流。

【步驟一】:定義/order/query接口

@GetMapping("/query")
public String queryOrder() {
    orderService.queryGoods();;
    return "查询order成功";
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

【步驟二】:定義/order/create介面

@GetMapping("/create")
public String createOrder() {
    // 查询商品
    orderService.queryGoods();
    // 查询订单
    System.out.println("新增订单");
    return "新增order成功";
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

【步驟三】:order-service服務中,為OrderService介面新增一個queryGoods方法:

public interface OrderService {

    /**
     * 创建订单
     */
    Long create(Order order);

    void queryGoods();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

【步驟四】:order-service服務中,為OrderService介面實作了OrderServiceImpl新增一個queryGoods方法:

@Override
@SentinelResource("goods")
public void queryGoods(){
    System.out.println("查询商品");
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

注意:

預設情況下,OrderService中的方法是不被Sentinel監控的,需要我們自己透過註解來標記要監控的方法。

給OrderServiceImpl的queryGoods方法加入@SentinelResource註解

【步驟五】:修改application.ym

在鏈路模式中,是對不同來源的兩個連結做監控。但是sentinel預設會為進入SpringMVC的所有請求設定同一個root資源,會導致連結模式失效。

我們需要關閉這種對SpringMVC的資源聚合,修改order-service服務的application.yml文件

spring:
  cloud:
    sentinel:
      web-context-unify: false # 关闭context整合
  • 1.
  • 2.
  • 3.
  • 4.

【步驟六】:為queryGoods設定限流規則,從/order/query進入queryGoods的方法限制QPS必須小於2

注意:設定規則之前同樣需要存取才會產生簇點鏈路,才可以針對性設定規則,因此需要重啟服務+存取新介面

圖片圖片

圖片圖片

只統計從/order/query進入/goods的資源,QPS閾值為2,超出則被限流。

【步驟七】 Jemter測試配置連結流控

啟動Jmeter壓測,預期/order/create不受影響,而/order/query最多允許放行流量=2

/order/create

圖片圖片

圖片圖片

/order/query

圖片圖片

圖片圖片

總結

流控模式有哪些?

  • 直接:對當前資源限流
  • 關聯:高優先級資源觸發閾值,對低優先級資源限流。
  • 連結:閾值統計時,只統計從指定資源進入目前資源的請求,是對請求來源的限流