令牌桶、漏斗、冷啓動限流在sentinel的應用

 分佈式系統爲了保證系統穩定性,在服務治理的限流中會根據不一樣場景進行限流操做,常見的限流算法有:html

  • 令牌桶:可容忍必定突發流量的速率的限流,令牌桶算法的原理是系統以恆定的速率產生令牌,而後把令牌放到令牌桶中,令牌桶有一個容量,當令牌桶滿了的時候,再向其中放令牌,那麼多餘的令牌會被丟棄;當想要處理一個請求的時候,須要從令牌桶中取出一個令牌,若是此時令牌桶中沒有令牌,那麼則拒絕該請求。java

  • 漏斗:固定速率限流,能夠啓動整流做用。node

在分析sentinel限流以前,咱們先看下sentinel是什麼,官網說明以下:算法

隨着微服務的流行,服務和服務之間的穩定性變得愈來愈重要。Sentinel 是面向分佈式服務架構的流量控制組件,主要以流量爲切入點,從流量控制、熔斷降級、系統自適應保護等多個維度來幫助您保障微服務的穩定性。架構

從限流角度來看,sentinel的限流有2種控制維度,一個是qps,一個是併發數。併發

qps這個很好理解,也就是每秒處理請求量,當超過設定閾值時,會進行流控,策略有以下幾種:拒絕、排隊(必定時長)等。app

併發數這個就是當前線程運行數,相似於hystrix,只不過sentinel是進行線程個數統計判斷是否達到線程設定值,而hystrix是根據不一樣線程池來作的。分佈式

sentinel中處理流程是一個責任鏈,不一樣功能的邏輯抽象成不一樣的ProcessorSlot組合在一塊兒,好比有限流的FlowSlot、打日誌的LogSot、數據統計的StatisticSlot。下面重點看限流的com.alibaba.csp.sentinel.slots.block.flow.FlowSlotide

public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                  boolean prioritized, Object... args) throws Throwable {
    // 是否觸發限流檢查
    checkFlow(resourceWrapper, context, node, count, prioritized);
    // 繼續往下一個節點走
    fireEntry(context, resourceWrapper, node, count, prioritized, args);
}

public void checkFlow(Function<String, Collection<FlowRule>> ruleProvider, ResourceWrapper resource,
                      Context context, DefaultNode node, int count, boolean prioritized) throws BlockException {
    Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
    for (FlowRule rule : rules) { // 多個限流規則檢查
        if (!canPassCheck(rule, context, node, count, prioritized)) {
            throw new FlowException(rule.getLimitApp(), rule);
        }
    }
}
// canPassCheck -> passLocalCheck
private static boolean passLocalCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount,
                                      boolean prioritized) {
    return rule.getRater().canPass(selectedNode, acquireCount, prioritized);
}

canPass校驗目前有如下幾種實現類:微服務

這幾個實現類分別使用了以下幾種限流算法:

  • DefaultController:令牌桶

  • RateLimiterController:漏斗

  • WarmUpController:冷啓動的令牌桶

  • WarmUpRateLimiterController:冷啓動的漏斗

sentinel中統計信息,好比qps、pass、block等信息都是在滑動時間窗口中維護的,好比時間戳是910時,統計信息會往對應800-1000的時間窗口更新,當時間戳是1001時,因爲時間窗口只有5個(每一個200ms),所以會複用第一個時間窗口,在使用前會先進行初始化該窗口統計值。

對於默認的流控實現 DefaultController,其是根據時間窗口的統計值是否達到了限流值來決定是否限流的,這也是把它歸爲令牌桶算法的緣由。漏斗算法實現RateLimiterController,會記錄上一次正常經過的時間戳信息(latestPassedTime),當判斷是否限流時,會根據當前時間-latestPassedTime是否大於間隔值,大於的話表示能夠正常經過,小於的話表示剛剛已經有流程正常經過,這次須要排隊等待,等待時間爲指望時間戳-當前時間戳,併發場景下,多個線程可能都會走到等待這裏,所以須要(cas操做)判斷當前需等待時間是否大於某個值,大於的話直接進行限流,再也不排隊等待。

冷啓動限流算法,即預熱/冷啓動方式。當系統長期處於低水位的狀況下,當流量忽然增長時,直接把系統拉昇到高水位可能瞬間把系統壓垮。經過"冷啓動",讓經過的流量緩慢增長,在必定時間內逐漸增長到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。

sentinel中一般冷啓動的過程系統容許經過的 QPS 曲線以下圖所示:

冷啓動的兩種模式,令牌桶和漏斗大同小異,只不過在流量較大時,冷啓動過程 令牌桶走勢相似於階梯向上直到設定的限流值,漏洞走勢相似於幾個斜線向上之道設定的限流值。

關於sentinel更多的知識可參考官方文檔:https://sentinelguard.io/zh-cn/docs/introduction.html

 

 推薦閱讀 

相關文章
相關標籤/搜索