Sentinel(六)之集群流控
轉載自??集群流控
介紹
為什么要使用集群流控呢?假設我們希望給某個用戶限制調用某個 API 的總 QPS 為 50,但機器數可能很多(比如有 100 臺)。這時候我們很自然地就想到,找一個 server 來專門來統計總的調用量,其它的實例都與這臺 server 通信來判斷是否可以調用。這就是最基礎的集群流控的方式。
另外集群流控還可以解決流量不均勻導致總體限流效果不佳的問題。假設集群中有 10 臺機器,我們給每臺機器設置單機限流閾值為 10 QPS,理想情況下整個集群的限流閾值就為 100 QPS。不過實際情況下流量到每臺機器可能會不均勻,會導致總量沒有到的情況下某些機器就開始限流。因此僅靠單機維度去限制的話會無法精確地限制總體流量。而集群流控可以精確地控制整個集群的調用總量,結合單機限流兜底,可以更好地發揮流量控制的效果。
集群流控中共有兩種身份:
- Token Client:集群流控客戶端,用于向所屬 Token Server 通信請求 token。集群限流服務端會返回給客戶端結果,決定是否限流。
- Token Server:即集群流控服務端,處理來自 Token Client 的請求,根據配置的集群規則判斷是否應該發放 token(是否允許通過)。
模塊結構
Sentinel 1.4.0 開始引入了集群流控模塊,主要包含以下幾部分:
- sentinel-cluster-common-default: 公共模塊,包含公共接口和實體
- sentinel-cluster-client-default: 默認集群流控 client 模塊,使用 Netty 進行通信,提供接口方便序列化協議擴展
- sentinel-cluster-server-default: 默認集群流控 server 模塊,使用 Netty 進行通信,提供接口方便序列化協議擴展;同時提供擴展接口對接規則判斷的具體實現(TokenService),默認實現是復用?sentinel-core?的相關邏輯
集群流控規則
規則
FlowRule?添加了兩個字段用于集群限流相關配置:
private boolean clusterMode; // 標識是否為集群限流配置 private ClusterFlowConfig clusterConfig; // 集群限流相關配置項其中 用一個專門的?ClusterFlowConfig?代表集群限流相關配置項,以與現有規則配置項分開:
// (必需)全局唯一的規則 ID,由集群限流管控端分配. private Long flowId;// 閾值模式,默認(0)為單機均攤,1 為全局閾值. private int thresholdType = ClusterRuleConstant.FLOW_THRESHOLD_AVG_LOCAL;private int strategy = ClusterRuleConstant.FLOW_CLUSTER_STRATEGY_NORMAL;// 在 client 連接失敗或通信失敗時,是否退化到本地的限流模式 private boolean fallbackToLocalWhenFail = true;- flowId?代表全局唯一的規則 ID,Sentinel 集群限流服務端通過此 ID 來區分各個規則,因此務必保持全局唯一。一般 flowId 由統一的管控端進行分配,或寫入至 DB 時生成。
- thresholdType?代表集群限流閾值模式。其中單機均攤模式下配置的閾值等同于單機能夠承受的限額,token server 會根據客戶端對應的 namespace(默認為?project.name?定義的應用名)下的連接數來計算總的閾值(比如獨立模式下有 3 個 client 連接到了 token server,然后配的單機均攤閾值為 10,則計算出的集群總量就為 30);而全局模式下配置的閾值等同于整個集群的總閾值。
ParamFlowRule?熱點參數限流相關的集群配置與?FlowRule?相似。
集群規則配置方式
在集群流控的場景下,我們推薦使用動態規則源來動態地管理規則。
對于客戶端,我們可以按照原有的方式來向?FlowRuleManager?和?ParamFlowRuleManager?注冊動態規則源,例如:
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser); FlowRuleManager.register2Property(flowRuleDataSource.getProperty());對于集群流控 token server,由于集群限流服務端有作用域(namespace)的概念,因此我們需要注冊一個自動根據 namespace 生成動態規則源的 PropertySupplier:
// Supplier 類型:接受 namespace,返回生成的動態規則源,類型為 SentinelProperty<List<FlowRule>> // ClusterFlowRuleManager 針對集群限流規則,ClusterParamFlowRuleManager 針對集群熱點規則,配置方式類似 ClusterFlowRuleManager.setPropertySupplier(namespace -> {return new SomeDataSource(namespace).getProperty(); });然后每當集群限流服務端 namespace set 產生變更時,Sentinel 會自動針對新加入的 namespace 生成動態規則源并進行自動監聽,并刪除舊的不需要的規則源。
集群限流客戶端
要想使用集群限流功能,必須引入集群限流 client 相關依賴:
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-cluster-client-default</artifactId><version>1.8.0</version> </dependency>用戶可以通過 API 將當前模式置為客戶端模式:
http://<ip>:<port>/setClusterMode?mode=<xxx>或者通過 ClusterStateManager API 手動指定模式:
// 指定當前身份為 Token Client ClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);其中 mode 為 0 代表 client(ClusterStateManager.CLUSTER_CLIENT),1 代表 server。設置成功后,若已有客戶端的配置,集群限流客戶端將會開啟并連接遠程的 token server。我們可以在?~/logs/csp/sentinel-record.log?日志中查看連接的相關日志。
若集群限流客戶端未進行配置,則用戶需要對客戶端進行基本的配置,比如指定集群限流 token server。我們提供了 API 進行配置:
http://<ip>:<port>/cluster/client/modifyConfig?data=<config>其中 data 是 JSON 格式的配置項:
- serverHost: token server host
- serverPort: token server 端口
- requestTimeout: 請求的超時時間(默認為 20 ms)
當然也可以通過動態配置源進行配置。集群限流 token client 共有兩種配置:
- 客戶端分配配置(ClusterClientAssignConfig),包括要連接的對端 token server 地址等相關信息。我們可以通過?ClusterClientConfigManager?的?registerServerAssignProperty?方法注冊動態配置源。分配配置通常通過統一的分配表解析而來,可以參考 embedded 模式 demo。
- 客戶端通信配置(ClusterClientConfig),包括通信的超時時長等配置。我們可以通過?ClusterClientConfigManager?的?registerClientConfigProperty?方法注冊動態配置源。
配置源注冊的相關邏輯可以置于?InitFunc?實現類中,并通過 SPI 注冊,在 Sentinel 初始化時即可自動進行配置源加載監聽。
若用戶未引入集群限流 client 相關依賴,或者 client 未開啟/連接失敗/通信失敗,則對于開啟了集群模式的規則:
- 集群熱點限流默認直接通過
- 普通集群限流會退化到 local 模式的限流,即在本地按照單機閾值執行限流檢查
當 token client 與 server 之間的連接意外斷開時,token client 會不斷進行重試,每次重試的間隔時間以?n * 2000 ms?的形式遞增。
集群限流服務端
要想使用集群限流服務端,必須引入集群限流 server 相關依賴:
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-cluster-server-default</artifactId><version>1.8.0</version> </dependency>啟動方式
Sentinel 集群限流服務端有兩種啟動方式:
- 獨立模式(Alone),即作為獨立的 token server 進程啟動,獨立部署,隔離性好,但是需要額外的部署操作。獨立模式適合作為 Global Rate Limiter 給集群提供流控服務。
- 嵌入模式(Embedded),即作為內置的 token server 與服務在同一進程中啟動。在此模式下,集群中各個實例都是對等的,token server 和 client 可以隨時進行轉變,因此無需單獨部署,靈活性比較好。但是隔離性不佳,需要限制 token server 的總 QPS,防止影響應用本身。嵌入模式適合某個應用集群內部的流控。
我們提供了 HTTP API 用于在 embedded 模式下轉換集群流控身份:
http://<ip>:<port>/setClusterMode?mode=<xxx>其中 mode 為?0?代表 client,1?代表 server,-1?代表關閉。注意應用端需要引入集群限流客戶端或服務端的相應依賴。
在獨立模式下,我們可以直接創建對應的?ClusterTokenServer?實例并在 main 函數中通過?start?方法啟動 Token Server。
規則配置
見前面?規則配置?相關內容。
屬性配置
我們推薦給集群限流服務端注冊動態配置源來動態地進行配置。配置類型有以下幾種:
- namespace set: 集群限流服務端的作用域(命名空間),用于指定該 token server 可以服務哪些應用或分組,嵌入模式下可以設置為自己的應用名。集群限流 client 在連接到 token server 后會上報自己的命名空間(默認為?project.name?配置的應用名),token server 會根據上報的命名空間名稱統計連接數。
- transport config: 集群限流服務端通信相關配置,如 server port
- flow config: 集群限流服務端限流相關配置,如滑動窗口統計時長、格子數目、最大允許總 QPS等
我們可以通過?ClusterServerConfigManager?的各個?registerXxxProperty?方法來注冊相關的配置源。
從 1.4.1 版本開始,Sentinel 支持給 token server 配置最大允許的總 QPS(maxAllowedQps),用于對 Token Server 的資源使用進行限制,防止在嵌入模式下影響應用本身。
Token Server 分配配置
示例
sentinel-demo-cluster 提供了嵌入模式和獨立模式的示例:
- sentinel-demo-cluster-server-alone:獨立模式 Demo
- sentinel-demo-cluster-embedded:嵌入模式 Demo,以 Web 應用為示例,可以啟動多個實例分別作為 Token Server 和 Token Client。數據源的相關配置可以參考?DemoClusterInitFunc。
注意:若在本地啟動多個 Demo 示例,需要加上?-Dcsp.sentinel.log.use.pid=true?參數,否則控制臺顯示監控會不準確。
集群限流控制臺
使用集群限流功能需要對 Sentinel 控制臺進行相關的改造,推送規則時直接推送至配置中心,接入端引入 push 模式的動態數據源。可以參考?Sentinel 控制臺(集群流控管理文檔)。
同時云上版本?AHAS Sentinel?提供開箱即用的全自動托管集群流控能力,無需手動指定/分配 token server 以及管理連接狀態,同時支持分鐘小時級別流控、大流量低延時場景流控場景,同時支持 Istio/Envoy 場景的 Mesh 流控能力。
其它
若在生產環境使用集群限流,管控端還需要關注以下的問題:
- Token Server 自動管理、調度(分配/選舉 Token Server)
- Token Server 高可用,在某個 server 不可用時自動 failover 到其它機器
集群流控日志
- ${log_dir}/sentinel-cluster-client.log:Token Client 日志,會記錄請求失敗的信息
擴展接口設計
整體擴展架構
通用擴展接口
以下通用接口位于?sentinel-core?中:
- TokenService: 集群限流功能接口,server / client 均可復用
- ClusterTokenClient: 集群限流功能客戶端
- ClusterTokenServer: 集群限流服務端接口
- EmbeddedClusterTokenServer: 集群限流服務端接口(embedded 模式)
以下通用接口位于?sentinel-cluster-common-default:
- EntityWriter
- EntityDecoder
Client 擴展接口
集群流控 Client 端通信相關擴展接口:
- ClusterTransportClient:集群限流通信客戶端
- RequestEntityWriter
- ResponseEntityDecoder
Server 擴展接口
集群流控 Server 端通信相關擴展接口:
- ResponseEntityWriter
- RequestEntityDecoder
集群流控 Server 端請求處理擴展接口:
- RequestProcessor: 請求處理接口 (request -> response)
總結
以上是生活随笔為你收集整理的Sentinel(六)之集群流控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C盘不停的被占满c盘莫名其妙被占满
- 下一篇: Sentinel(七)之网关限流