Sentinel 發佈里程碑版本,添加集羣流控功能

自去年10月底發佈GA版本後,Sentinel在近期發佈了另外一個里程碑版本v1.4(最新的版本號是v1.4.1),加入了開發者關注的集羣流控功能。java

集羣流控簡介

爲何要使用集羣流控呢?假設咱們但願給某個用戶限制調用某個 API 的總 QPS 爲 50,但機器數可能不少(好比有 100 臺)。這時候咱們很天然地就想到,找一個 server 來專門來統計總的調用量,其它的實例都與這臺 server 通訊來判斷是否能夠調用。這就是最基礎的集羣流控的方式。json

那麼這個 server 如何部署呢?最直觀的方式就是做爲獨立的 token server 進程啓動,獨立部署:app

sentinel-cluster-alone

另外一種就是嵌入模式(Embedded),即做爲內置的 token server 與服務在同一進程中啓動,無需單獨部署:ide

sentinel-cluster-embedded

另外集羣流控還能夠解決流量不均勻致使整體限流效果不佳的問題。假設集羣中有 10 臺機器,咱們給每臺機器設置單機限流閾值爲 10 QPS,理想狀況下整個集羣的限流閾值就爲 100 QPS。不過實際狀況下流量到每臺機器可能會不均勻,會致使總量沒有到的狀況下某些機器就開始限流:spa

flow-not-avg-in-cluster

所以僅靠單機維度去限制的話會沒法精確地限制整體流量。而集羣流控能夠精確地控制整個集羣的調用總量,結合單機限流兜底,能夠更好地發揮流量控制的效果。3d

Sentinel 1.4.0 開始引入了集羣流控模塊,主要分爲兩個部分:Token Client 和 Token Server:code

  • Token Client 即集羣流控客戶端,用於向所屬 Token Server 通訊請求 token。集羣限流服務端會返回給客戶端結果,決定是否限流。Sentinel 集羣流控的通訊底層採用 Netty 實現。
  • Token Server 即集羣流控服務端,處理來自 Token Client 的請求,根據配置的集羣規則判斷是否應該發放 token(是否容許經過)。

Sentinel 集羣流控支持限流規則熱點規則兩種規則。集羣流控支持兩種形式的閾值計算方式:cdn

  • 集羣整體模式:即限制整個集羣內的某個資源的整體 QPS 不超過此閾值。
  • 單機均攤模式:單機均攤模式下配置的閾值等同於單機可以承受的限額,Token Server 會根據鏈接數來計算總的閾值(好比獨立模式下有 3 個 client 鏈接到了 token server,而後配的單機均攤閾值爲 10,則計算出的集羣總量就爲 30),按照計算出的總的閾值來進行限制。這種方式根據當前的鏈接數實時計算總的閾值,對於機器常常進行變動的環境很是適合。

部署方式

Sentinel 集羣流控服務端支持獨立模式(Alone)以及嵌入模式(Embedded)。二者的優缺點對比:server

  • 獨立模式做爲獨立的 token server 進程啓動,獨立部署,隔離性好,可是須要額外的部署操做。獨立模式適合做爲 Global Rate Limiter 給整個集羣提供流控服務。
  • 嵌入模式做爲內置的 token server 嵌入到應用進程中。嵌入模式下集羣中各個實例都是對等的,token server 和 client 能夠隨時進行轉變,無需單獨部署,靈活性比較好。但缺點就是隔離性不佳, 須要限制 token server 的總 QPS,防止影響應用自己。嵌入模式適合某個應用集羣內部的流控。

Sentinel 提供 API 來對 client / server 進行配置以及指定模式,可是機器多的時候不方便進行管理。通常咱們須要經過 Sentinel 控制檯的集羣流控管理功能來統一管理某個應用集羣下全部的 token server 和 token client,靈活進行分配。xml

配置

配置是集羣流控中比較重要的一部分。Sentinel 集羣流控的配置主要包含幾部分:

集羣規則配置

集羣規則配置須要藉助動態規則源。以集羣流控規則爲例,對於客戶端,咱們能夠用以前的方式向 FlowRuleManager 註冊動態規則源。而對於 Token Server,咱們須要向集羣規則管理器 ClusterFlowRuleManager 註冊規則源。咱們推薦的方式是在應用端註冊動態規則源,而後在 Sentinel 控制檯直接推送規則到配置中心,即 push 模式:

Remote push rules to config center

Token Server / Client 的分配

以嵌入模式爲例,一個比較好的實踐是:結合流量分佈和實時負載狀況來在服務集羣中選取幾臺較爲空閒的機器做爲 Token Server,其它的機器做爲 Token Client,劃分紅幾組,分別歸屬各自的 Token Server 管理。最後組成一個映射表,相似於:

// ip: token server IP, port: token server port, clientSet: 所管轄的 token client 集合
[{"clientSet":["112.12.88.66@8729","112.12.88.67@8727"],"ip":"112.12.88.68","machineId":"112.12.88.68@8728","port":11111}]
複製代碼

assign-topology

而後像 Token Client / Token Server 通訊配置、集羣流控模式等配置源均可以監聽這個分配映射表對應的數據源,來解析本身的身份和相關通訊配置。當分配映射表變動時每臺機器對應的身份和配置也會實時變動,實時生效。Sentinel 1.4.1 改進了 Sentinel 控制檯集羣流控的管理頁面,能夠直接以應用維度來分配 Token Server。能夠參考本文後面的指引來使用。

其它配置

其它的配置好比 Token Server 的命名空間集合(namespace set,用於指定該 Token Server 能夠爲哪些應用/分組服務)、最大容許的總 QPS 等,既能夠經過 Sentinel 預留的 HTTP API 來變動配置,也能夠經過註冊動態配置源來進行配置。

快速使用集羣流控

下面咱們來看一下如何快速使用集羣流控功能。接入集羣流控模塊的步驟以下:

(1)引入集羣流控依賴

這裏咱們以嵌入模式來運行 token server,即在應用集羣中指定某臺機器做爲 token server,其它的機器指定爲 token client。

首先咱們引入集羣流控相關依賴:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-client-default</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-server-default</artifactId>
    <version>1.4.1</version>
</dependency>
複製代碼

(2)配置動態規則源

要想使用集羣流控功能,咱們須要在應用端配置動態規則源,並經過 Sentinel 控制檯實時進行推送。流程以下所示:

Remote push rules to config center

以流控規則爲例,假設咱們使用 ZooKeeper 做爲配置中心,則能夠向客戶端 FlowRuleManager 註冊 ZooKeeper 動態規則源:

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, path, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
複製代碼

另外咱們還須要針對 Token Server 註冊集羣規則數據源。因爲嵌入模式下 token server 和 client 能夠隨時變換,所以咱們只需在每一個實例都向集羣流控規則管理器 ClusterFlowRuleManager 註冊動態規則源便可。Token Server 抽象出了命名空間(namespace)的概念,能夠支持多個應用/服務,所以咱們須要註冊一個自動根據 namespace 建立動態規則源的生成器:

// Supplier 會根據 namespace 生成的動態規則源,類型爲 SentinelProperty<List<FlowRule>>,針對不一樣的 namespace 生成不一樣的規則源(監聽不一樣 namespace 的 path).
// 默認 namespace 爲應用名(project.name)
// ClusterFlowRuleManager 針對集羣限流規則,ClusterParamFlowRuleManager 針對集羣熱點規則,配置方式相似
ClusterFlowRuleManager.setPropertySupplier(namespace -> {
    return new SomeDataSource(address, dataIdPrefix + namespace).getProperty();
});
複製代碼

(3)控制檯進行改造適配動態規則源

咱們只需簡單對 Sentinel 控制檯進行改造便可直接將流控規則推送至配置中心。從 Sentinel 1.4.0 開始,Sentinel 控制檯提供 DynamicRulePublisherDynamicRuleProvider 接口用於實現應用維度的規則推送和拉取,並提供了 Nacos 推送的示例(位於 test 目錄下)。咱們只須要實現本身的 DynamicRulePublisherDynamicRuleProvider 接口並在 FlowControllerV2 類中相應位置經過 @Qualifier 註解指定對應的 bean name 便可,相似於:

@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
複製代碼

Sentinel 控制檯提供應用維度推送的頁面(/v2/flow)。在上述配置完成後,咱們能夠在此頁面向配置中心推送規則:

flow-rule-v2

(4)控制檯分配 Token Server

當上面的步驟都完成後,咱們就能夠在 Sentinel 控制檯的「集羣流控」 Token Server 列表頁面管理分配 token server 了。假設咱們啓動了三個應用實例,咱們選擇一個實例爲 token server,其它兩個爲 token client:

token server assignment

頁面上機器的顯示方式爲 ip@commandPort,其中 commandPort 爲應用端暴露給 Sentinel 控制檯的端口。選擇好之後,點擊 保存 按鈕,刷新頁面便可以看到 token server 分配成功:

image

而且咱們能夠在頁面查看 token server 的鏈接狀況:

image

(5)配置規則,觀察效果

接下來咱們配置一條集羣限流規則,限制 com.alibaba.csp.sentinel.demo.cluster.app.service.DemoService:sayHello(java.lang.String) 資源的集羣總 QPS 爲 10,選中「是否集羣」選項,閾值模式選擇整體閾值

set-cluster-rules

模擬流量同時請求這三臺機器,過一段時間後觀察效果。能夠在監控頁面看到對應資源的集羣維度的總 QPS 穩定在 10:

monitoring-10qps

總結

集羣流控可以精確地控制整個集羣的 QPS,結合單機限流兜底,能夠更好地發揮流量控制的效果。還有更多的場景等待你們發掘,好比:

  • 在 API Gateway 處統計某個 API 的總訪問量,並對某個 API 或服務的總 QPS 進行限制
  • Service Mesh 中對服務間的調用進行全局流控
  • 集羣內對熱點商品的總訪問頻次進行限制

儘管集羣流控比較好用,但它不是萬能的,只有在確實有必要的場景下才推薦使用集羣流控。

另外若在生產環境使用集羣限流,管控端還須要關注如下的問題:

  • Token Server 自動管理(分配/選舉 Token Server)
  • Token Server 高可用,在某個 server 不可用時自動 failover 到其它機器

將來咱們還計劃實現集羣流控多語言版本的客戶端,並對接 Service Mesh,讓 Sentinel 集羣流控能夠在更多場景下使用。

相關文章
相關標籤/搜索