Sentinel流控規則可以這樣玩?

2022-05-25 12:02:36

專案原始碼地址:公眾號回覆 sentinel,即可免費獲取原始碼

前言

上一篇文章中,我們講解了關於sentinel基本介紹以及流控規則中直接和快速失敗的效果,有興趣的可以去看上一篇文章,今天,我們給大家帶來更加詳細的關於sentinel流控規則的介紹。今天的內容我們主要圍繞四個點進行展開介紹。

  • 流控模式 :關聯、鏈路
  • 流控效果 :Warm Up、排隊等待


這四點具體是什麼意思呢?別急我們一個一個來做詳細的介紹,首先我們從關聯開始。

首先啟動專案:cloud-alibaba-sentinel-8006

關聯

在官方的介紹中是這樣說的:關聯的資源達到閾值時,就限流自己。

這句話是什麼意思呢?用比較直白一點的話來講,假設我們有A和B兩個介面,當A關聯B介面,同時B介面的資源達到設定的閾值時,限流A。我們也可以理解成,當我們下游的服務出現存取壓力過大時,對上游的服務進行攔截和限流操作,例如:電商系統,當我們訂單系統超出承受閾值時,對我們支付模組進行限流。

例如:當我們關聯order介面達到我們設定的閾值時,限流pay的介面存取。

@Slf4j
@RestController
public class TestController {

    @GetMapping("/pay")
    public String pay() {
        return "hello my name is pay ,wo shi boy";
    }

    @GetMapping("/order")
    public String order(){
        return "hi my name is order, me is girl";
    }

}

給pay介面新增流控規則

在這裡我們需要使用到postMan工具,來模擬並行存取,用它來測試我們的order介面的並行存取。

在這裡的意思是25個執行緒0.25秒跑一次,當我們跑起來之後,再去存取pay介面就可以看到以下資訊


當我們對order介面進行並行存取的時候,這個時候我們去存取pay介面,就可以看到pay介面返回限流資訊

鏈路

接下來我們就來看一下流控模式中的鏈路,鏈路的意思是值當某個介面過來的資源達到閾值時,開啟限流,主要是針對於請求來源的微服務,具有更細顆粒度。

比如在一個服務應用中,多個(pay和order)介面都呼叫了同一個服務中的方法(該方法必須使用註解 SentinelResource進行修飾),如果頻繁的去請求pay介面,並且達到設定的閾值,這麼時候我們再去請求order介面,那麼呼叫了同一服務的order介面就會被限流

test類

@Service
public class TestService {
    // 定義限流資源
    @SentinelResource("end")
    public String end(){
        return "end method";
    }
}

controller類

@Slf4j
@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/pay")
    public String pay() {
        return testService.end();
    }

    @GetMapping("/order")
    public String order(){
        return testService.end();
    }

}

設定項web-context-unify,這個設定的意思是說根據不同的URL進行鏈路限流,否則沒有效果

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #設定Sentinel地址,就是我們的WEB介面
        dashboard: localhost:8080
        #Sentinel設定預設8719埠,被佔用埠會自動從+1,直到找到未被佔用的埠
        port: 8719
        # 設定為false
      web-context-unify: false

我們存取pay介面和order介面後,需要對end進行流控規則的設定,也就是使用了SentinelResource註解標註的方法進行流控設定。

那麼這個時候如果我們頻繁的去存取order介面的時候,就會出現異常的情況,直接丟擲錯誤提示,這個也是因為快速失敗在鏈路上的直接體現

Warm Up

參考檔案:https://sentinelguard.io/zh-cn/docs/flow-control.html

Warm Up 流量控制,也叫預熱或者冷啟動方式,會根據我們設定的規則,進行緩慢的流量放開,逐漸增加閾值上限,給系統一個反應時間,避免流量的突然增加,將系統壓垮的情況發生,主要用於預防我們系統長期處於穩定的流量存取下,突然流量的增加,將系統資源直接拉滿的情況.

在這裡我們主要弄明白兩個引數

單機閾值:12,這個表示我們存取最大閾值為12,但是第一次最大存取量為4,為什麼是4呢,看下面公式

預熱公式:閾值/coldFactor(預設值為3),經過預熱時間後才會達到閾值。

預熱時長:5 ,也就是說我們的請求會在五秒內單機閾值達到12的存取,比如第一次為4,後續在五秒內依次5/6/8/10,最後達到12的閾值

一般這種在秒殺或者電商節中會設定這樣的流控規則,就是為了防止突然流量的增加導致系統的奔潰。

當我們設定完流控規則以後,我們就來看一下效果,我們剛才設定的order的介面,如果當我們在頻繁的去存取order介面的時候,如果超過當前時間設定的閾值時,直接返回限流資訊。

在這裡我們直接用瀏覽器瘋狂的去重新整理,是時候體驗單身二十幾年的手速了,當然也可以使用postman介面去試,我們這邊手速比較快,直接用瀏覽器重新整理,我們可以看到下面的曲線圖:

藍色表示你拒絕的QPS,綠色表示通過的QPS,我們可以看到藍色成明顯的下降趨勢,而綠色成上升趨勢,也可以通過右邊的表格中看到,剛開始通過的只有四個,具體的有三個,後面通過慢慢增加,拒絕慢慢變少,這個就是我們Warm Up(預熱)的作用了

排隊等待

我們現在來介紹最後一個流控規則的使用,排隊等待會嚴格控制請求通過的間隔時間,讓請求穩定且勻速的通過,可以用來處理間隔性突發的高流量,例如搶票軟體,在某一秒或者一分鐘內有大量的請求到來,而接下來的一段時間裡處於空閒狀態,我們希望系統能夠在接下來的空餘時間裡也能出去這些請求,而不是直接拒絕。

以固定的間隔時間讓請求通過,當請求過來的時候,如果當前請求距離上一個請求通過的時間大於 規則預設值 ,則請求通過,如果當前請求預期通過時間小於 規則預設值 ,則進行排隊等待,如果預期通過時間超過最大排隊時間,直接拒絕請求。

Sentinel排隊等待是 漏銅演演算法+虛擬佇列機制實現的,目前排隊等待中不支援QPS>1000的場景

我們對pay介面進行設定,一秒鐘只處理一個QPS請求,其他的排隊,如果超過15秒則直接拒絕

pay介面調整,這裡我們給pay介面加上列印紀錄檔,方便我們看到具體效果

    @GetMapping("/pay")
    public String pay() {
//        return "hello my name is pay ,wo shi boy";
        log.info("pay介面,請求執行緒為:"+Thread.currentThread().getName());
        return testService.end();
    }

我們藉助postman來進行呼叫,說明手速始終更不上工具,還是工具香,這裡我們設定10個請求,沒有間隔時間

從下圖中我們可以看到,對於我們的請求,是一個QPS請求。

總結

到這裡呢,我們的流控規則就講完了,主要是針對不同的規則進行不同的設定,來滿足我們不用業務場景,可能會有一點點的小饒,但是如果親自操作之後,會感覺原來是這樣,感興趣的小夥伴可以自己動手試一試,原始碼都已經上傳了,只有動手了才能感受到其中的快樂,趕緊去試一試吧。

我是牧小農,怕什麼真理無窮,進一步有進一步的歡喜,大家加油!