戰(zhàn):基于 gRPC 為 Envoy 提供全局限流服務(wù))
后端微服務(wù)【免費(fèi)下載鏈接】SentinelA powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服務(wù)的高可用流控防護(hù)組件)項(xiàng)目地址https://gitcode.com/gh_mirrors/sentine/Sentinel點(diǎn)擊查看免費(fèi)下載本篇指南以倉(cāng)庫(kù)中 sentinel-cluster-server-envoy-rls 模塊為主線講解如何用 Sentinel 集群 Token Server 實(shí)現(xiàn) Envoy 全局限流Global Rate Limiting的 gRPC 服務(wù)端覆蓋構(gòu)建打包、YAML 規(guī)則配置、動(dòng)態(tài)熱加載、運(yùn)行參數(shù)調(diào)優(yōu)以及 Kubernetes 環(huán)境下與 Envoy 的完整聯(lián)調(diào)方案。讀完本文你將掌握 RLS v2/v3 API 的服務(wù)端實(shí)現(xiàn)原理并能獨(dú)立部署一套Envoy 網(wǎng)關(guān) Sentinel 限流服務(wù)的云原生限流體系。模塊定位與工作原理Envoy 自身提供兩種限流能力本地限流local rate limiting與全局限流global rate limiting。全局限流需要調(diào)用外部限流服務(wù)Envoy 通過(guò) gRPC 將限流請(qǐng)求攜帶 domain 與 rate limit descriptors發(fā)送給限流服務(wù)器由服務(wù)器統(tǒng)一決策后返回OK或OVER_LIMIT。Sentinel 的sentinel-cluster-server-envoy-rls模塊正是這一 gRPC 限流服務(wù)端的 Sentinel 實(shí)現(xiàn)——它把 Envoy 傳來(lái)的限流描述符轉(zhuǎn)換為 Sentinel 的集群流控規(guī)則再交給 Sentinel 集群 Token Server 的令牌判定鏈路完成計(jì)數(shù)與限流。該模塊的入口類為 SentinelEnvoyRlsServer.java其啟動(dòng)流程清晰可見(jiàn)將project.name設(shè)為sentinel-rls-token-server使 Sentinel 日志與監(jiān)控歸屬于該應(yīng)用初始化EnvoyRlsRuleDataSourceService加載并監(jiān)聽規(guī)則文件解析 gRPC 監(jiān)聽端口默認(rèn) 10245啟動(dòng) SentinelRlsGrpcServer.java注冊(cè) JVM 關(guān)閉鉤子在進(jìn)程退出時(shí)依次關(guān)閉 gRPC 服務(wù)與數(shù)據(jù)源調(diào)用InitExecutor.doInit()完成 Sentinel 內(nèi)部組件的初始化隨后阻塞直至服務(wù)關(guān)閉。gRPC 服務(wù)端同時(shí)注冊(cè)了兩個(gè)限流服務(wù)實(shí)現(xiàn)v3 版本的 SentinelEnvoyRlsServiceImpl.java 與 v2 版本的SentinelEnvoyRlsServiceImpl位于service包下。這意味著單個(gè)進(jìn)程可同時(shí)兼容 Envoy RLS v2 與 v3 兩種 API。需要注意的是Envoy 自 1.18.0 起已移除 v2 API 支持因此新部署的環(huán)境應(yīng)優(yōu)先使用 v3 API。說(shuō)明RLS 服務(wù)所需的 gRPC stub 類并非倉(cāng)庫(kù)中手工維護(hù)而是由protobuf-maven-plugin在 Maven 的compile階段根據(jù) src/main/proto 目錄下的 proto 定義自動(dòng)生成生成產(chǎn)物位于構(gòu)建目錄target/generated-sources/protobuf。proto 文件覆蓋envoy.service.ratelimit.v2/v3、envoy.extensions.common.ratelimit.v3等 Envoy 官方限流協(xié)議定義還有udpa/annotations與validate等依賴項(xiàng)。構(gòu)建可執(zhí)行 JAR在sentinel-cluster-server-envoy-rls模塊目錄下執(zhí)行以下命令構(gòu)建可執(zhí)行 JAR構(gòu)建產(chǎn)物為目標(biāo)jar包含全部運(yùn)行依賴mvn clean package -P prod激活prodprofile 會(huì)一并打包出可運(yùn)行的 fat jar。構(gòu)建完成后即可通過(guò)java -jar啟動(dòng)限流服務(wù)啟動(dòng)前必須配置規(guī)則文件路徑見(jiàn)下文配置項(xiàng)一節(jié)。規(guī)則配置domain 與 descriptors 模型Sentinel RLS Token Server 支持通過(guò) YAML 文件動(dòng)態(tài)配置規(guī)則。要理解規(guī)則文件的結(jié)構(gòu)先要理解 Envoy 側(cè)的限流請(qǐng)求模型domain域限流請(qǐng)求的命名空間對(duì)應(yīng) Envoy 配置中envoy.filters.http.ratelimit過(guò)濾器的domain字段。規(guī)則文件中的domain必須與 Envoy 配置一致才生效rate limit descriptor限流描述符一次限流請(qǐng)求可能攜帶多個(gè)描述符每個(gè)描述符由 Envoy 的路由rate_limitsactions 生成entry條目描述符內(nèi)部的鍵值對(duì)如destination_cluster: service_httpbin。Sentinel 為同一個(gè) domain 下每個(gè)限流描述符分別設(shè)置獨(dú)立閾值。規(guī)則文件的結(jié)構(gòu)模型對(duì)應(yīng)源碼中的 EnvoyRlsRule.java頂層包含domain與descriptors列表每個(gè) descriptor 包含resources鍵值對(duì)集合對(duì)應(yīng) Envoy 描述符條目與count閾值。規(guī)則文件示例domain: foo descriptors: - resources: - key: destination_cluster value: service_httpbin count: 1以上規(guī)則僅對(duì) domainfoo生效含義是所有發(fā)往service_httpbin集群的請(qǐng)求最大 QPS 被限制為 1。規(guī)則的加載與轉(zhuǎn)換規(guī)則文件通過(guò) EnvoyRlsRuleDataSourceService.java 加載。該數(shù)據(jù)源基于 Sentinel 的FileRefreshableDataSource實(shí)現(xiàn)用 SnakeYAML 將文件內(nèi)容反序列化為EnvoyRlsRule對(duì)象Representer配置了setSkipMissingProperties(true)缺失字段不會(huì)導(dǎo)致解析失敗數(shù)據(jù)源持有SentinelProperty規(guī)則文件內(nèi)容一旦變化會(huì)推送新規(guī)則到EnvoyRlsRuleManager實(shí)現(xiàn)無(wú)重啟熱更新啟動(dòng)時(shí)若未配置規(guī)則文件路徑會(huì)拋出IllegalStateException并提示設(shè)置SENTINEL_RLS_RULE_FILE_PATH環(huán)境變量。收到新規(guī)則后EnvoyRlsRuleManager.java 內(nèi)部監(jiān)聽器會(huì)做以下處理校驗(yàn)規(guī)則合法性isValidRuledomain 非空、descriptors 非空、每個(gè) descriptor 的count非空且不小于 0、resources非空且每個(gè)條目的 key/value 均非空同一 domain 重復(fù)出現(xiàn)時(shí)僅保留第一條并打印警告日志通過(guò) EnvoySentinelRuleConverter.java 將每條規(guī)則轉(zhuǎn)換為 Sentinel 集群FlowRule使用|分隔符拼接domain|key|value...作為資源標(biāo)識(shí)并生成對(duì)應(yīng)的集群流控 IDInteger.MAX_VALUE key.hashCode()偏移避免負(fù)數(shù)最終調(diào)用ClusterFlowRuleManager.loadRules(ServerConstants.DEFAULT_NAMESPACE, flowRules)加載到默認(rèn)命名空間的集群流控規(guī)則庫(kù)。規(guī)則的校驗(yàn)方法規(guī)則的合法性校驗(yàn)邏輯完整體現(xiàn)在EnvoyRlsRuleManager.isValidRule()中其約束可作為配置時(shí)的自查清單校驗(yàn)維度約束條件domain非空字符串descriptors非空列表descriptor.count非空且 ≥ 0descriptor.resources非空集合resource.key / value均非空字符串規(guī)則生效后的驗(yàn)證方式規(guī)則加載是否成功有兩種驗(yàn)證途徑查看日志Sentinel 運(yùn)行日志位于~/logs/csp/sentinel-record.log.xxx規(guī)則加載時(shí)會(huì)輸出[EnvoyRlsRuleManager] Envoy RLS rules loaded: [...]記錄含轉(zhuǎn)換后的 FlowRule 明細(xì)查詢命令接口訪問(wèn)localhost:8719/cluster/server/flowRules可查看轉(zhuǎn)換后已生效的集群流控規(guī)則列表。8719 為 Sentinel 命令端口與 K8s 示例中暴露的 command port 一致。請(qǐng)求判定鏈路v3 服務(wù)端實(shí)現(xiàn)當(dāng) Envoy 調(diào)用 gRPC 限流服務(wù)時(shí)v3 實(shí)現(xiàn)SentinelEnvoyRlsServiceImpl.shouldRateLimit()的執(zhí)行流程如下解析request.getHitsAddend()作為本次扣減的令牌數(shù)小于 0 時(shí)報(bào)錯(cuò)拒絕等于 0未設(shè)置時(shí)按 1 處理取出請(qǐng)求中的 domain遍歷每個(gè)RateLimitDescriptor將描述符條目用|拼接生成 key調(diào)用EnvoySentinelRuleConverter.generateFlowId()計(jì)算規(guī)則 ID從ClusterFlowRuleManager中查找對(duì)應(yīng)FlowRule若規(guī)則不存在視為NO_RULE_EXISTS請(qǐng)求直接放行OK若規(guī)則存在則通過(guò)SimpleClusterFlowChecker.acquireClusterToken()執(zhí)行集群令牌判定返回OK或OVER_LIMIT每個(gè)描述符生成一個(gè)DescriptorStatus含Code、currentLimit與limitRemaining任一描述符被限流則整體overallCode置為OVER_LIMIT若開啟了訪問(wèn)日志會(huì)記錄 domain、描述符原文、判定狀態(tài)與剩余額度。配置項(xiàng)一覽模塊的配置項(xiàng)通過(guò)環(huán)境變量或 JVM 系統(tǒng)屬性注入。所有常量定義在 SentinelEnvoyRlsConstants.java 中。配置解析遵循系統(tǒng)環(huán)境變量?jī)?yōu)先于 JVM 屬性的順序見(jiàn)SentinelEnvoyRlsServer.resolvePort()與EnvoyRlsRuleDataSourceService.getRuleConfigPath()的實(shí)現(xiàn)。配置項(xiàng)環(huán)境變量配置項(xiàng)JVM 屬性說(shuō)明默認(rèn)值是否必填SENTINEL_RLS_GRPC_PORTcsp.sentinel.grpc.server.portRLS gRPC 服務(wù)監(jiān)聽端口10245否SENTINEL_RLS_RULE_FILE_PATHcsp.sentinel.rls.rule.fileRLS 規(guī)則 YAML 文件路徑無(wú)是SENTINEL_RLS_ACCESS_LOG無(wú)是否開啟訪問(wèn)日志設(shè)為on開啟輸出到控制臺(tái)off否端口默認(rèn)值說(shuō)明模塊 README 的配置表中寫的是 10240但源碼常量SentinelEnvoyRlsConstants.DEFAULT_GRPC_PORT的取值為10245且 K8s 示例sentinel-rls.yml、envoy-v3-api.yml中 Envoy 與 RLS 服務(wù)交互的端口均為 10245。實(shí)際部署時(shí)請(qǐng)以 10245 為準(zhǔn)或通過(guò)環(huán)境變量顯式覆蓋端口。端口解析還帶有健壯性保護(hù)環(huán)境變量或?qū)傩灾械亩丝谌魹榭?、非法或超?165535 范圍會(huì)打印警告并回退到默認(rèn)端口 10245。Kubernetes 環(huán)境部署實(shí)戰(zhàn)模塊在 sample/k8s 目錄下提供了完整的 K8s 部署樣例包含三個(gè) YAML 模板。第一步準(zhǔn)備鏡像可以直接使用官方預(yù)構(gòu)建鏡像registry.cn-hangzhou.aliyuncs.com/sentinel-docker-repo/sentinel-envoy-rls-server:latest也可以在sentinel-cluster-server-envoy-rls目錄下基于倉(cāng)庫(kù)自帶 Dockerfile 自行構(gòu)建docker build -t sentinel/sentinel-envoy-rls-server:latest -f ./Dockerfile .第二步部署 Sentinel RLS Token Serversentinel-rls.yml 模板包含三個(gè)資源對(duì)象ConfigMapsentinel-rule-cm承載限流規(guī)則 YAMLkey 為rule-yaml通過(guò) volume 掛載進(jìn) Deployment規(guī)則更新即時(shí)生效Deploymentsentinel-rls-server運(yùn)行 RLS 服務(wù)容器暴露 10245gRPC與 8719命令端口通過(guò)環(huán)境變量SENTINEL_RLS_RULE_FILE_PATH/tmp/sentinel/rule.yaml指定掛載后的規(guī)則文件路徑Servicesentinel-rls-serviceClusterIP 類型同時(shí)導(dǎo)出 8719 與 10245 端口供集群內(nèi) Envoy pod 訪問(wèn)。樣例中的限流規(guī)則即為上文僅對(duì) domain foo 的 service_httpbin 集群限流 QPS1的配置。若需開啟訪問(wèn)日志在 Deployment 的 env 中加入env: - name: SENTINEL_RLS_ACCESS_LOG value: on此外可通過(guò)JAVA_OPTS環(huán)境變量追加 JVM 啟動(dòng)參數(shù)如-Dcsp.sentinel.rls.rule.file...。執(zhí)行部署kubectl apply -f sample/k8s/sentinel-rls.yml第三步部署 Envoyenvoy-v3-api.yml 提供了完整的 Envoy 部署模板Envoy v1.20.1 鏡像配置了兩個(gè) Envoy clusterservice_httpbin指向 httpbin.org 的 HTTP 代理與rate_limit_cluster指向sentinel-rls-service:10245即 Sentinel RLS 服務(wù)啟用http2_protocol_options以支持 gRPCrate limit filter在 HTTP filter chain 中加入envoy.filters.http.ratelimitdomain: foo與規(guī)則文件匹配request_type: external表示僅對(duì)外部請(qǐng)求做限流failure_mode_deny: false表示限流服務(wù)不可用時(shí)放行transport_api_version: V3指定使用 v3 API路由限流動(dòng)作在route_config中配置rate_limitsaction{destination_cluster: {}}該動(dòng)作會(huì)生成包含實(shí)際目標(biāo)集群名如service_httpbin的限流描述符Sentinel 據(jù)此按目標(biāo)集群分別限流。若已有運(yùn)行中的 Envoy 實(shí)例只需將限流集群地址指向sentinel-rls-service、端口 10245 即可。執(zhí)行部署kubectl apply -f sample/k8s/envoy-v3-api.yml倉(cāng)庫(kù)還同時(shí)提供了 v2 API 版本的樣例 envoy-legacy-v2-api.yml供仍在使用舊版 Envoy 1.18.0的場(chǎng)景參考。第四步驗(yàn)證限流效果部署完成后在 K8s pod 內(nèi)訪問(wèn)envoy-service:10000/json。由于規(guī)則將 QPS 上限設(shè)為 1并發(fā)請(qǐng)求時(shí)只有第一個(gè)請(qǐng)求通過(guò)后續(xù)請(qǐng)求被限流并返回 HTTP 429返回 200放行返回 429觸發(fā)限流。第五步動(dòng)態(tài)更新規(guī)則直接修改 ConfigMapsentinel-rule-cm中的rule-yaml內(nèi)容并應(yīng)用。由于 ConfigMap 以 volume 方式掛載Sentinel 通過(guò)FileRefreshableDataSource感知到文件內(nèi)容變化后會(huì)自動(dòng)將新規(guī)則加載到EnvoyRlsRuleManager并同步到集群流控規(guī)則庫(kù)全程無(wú)需重啟任何服務(wù)。測(cè)試用例與內(nèi)部細(xì)節(jié)倉(cāng)庫(kù)內(nèi)置了針對(duì)核心鏈路的單元測(cè)試可作為理解行為細(xì)節(jié)的參考EnvoySentinelRuleConverterTest.java驗(yàn)證 Envoy RLS 規(guī)則到 Sentinel FlowRule 的轉(zhuǎn)換邏輯包括規(guī)則 ID 生成與資源標(biāo)識(shí)拼接SentinelEnvoyRlsServiceImplTest.java 與 service/v3 下的同名測(cè)試驗(yàn)證 v2/v3 服務(wù)實(shí)現(xiàn)的請(qǐng)求判定行為例如描述符無(wú)對(duì)應(yīng)規(guī)則時(shí)放行、超限時(shí)返回OVER_LIMIT、hitsAddend缺失時(shí)按 1 處理等。兩個(gè)值得注意的設(shè)計(jì)細(xì)節(jié)無(wú)規(guī)則即放行若請(qǐng)求描述符在規(guī)則庫(kù)中找不到對(duì)應(yīng) FlowRule服務(wù)端直接返回OK避免因規(guī)則缺失導(dǎo)致業(yè)務(wù)流量被誤殺access log 支持RlsAccessLogger.java 在開啟SENTINEL_RLS_ACCESS_LOGon時(shí)記錄每條限流請(qǐng)求的 domain、描述符、判定狀態(tài)與剩余額度便于線上排查限流命中情況。小結(jié)sentinel-cluster-server-envoy-rls將 Sentinel 的集群流控能力封裝為標(biāo)準(zhǔn)的 Envoy 全局限流 gRPC 服務(wù)通過(guò)一份 YAML 規(guī)則文件domain descriptors count即可對(duì) Envoy 路由維度如目標(biāo)集群、請(qǐng)求頭等的流量做細(xì)粒度限流規(guī)則熱更新、v2/v3 雙 API 兼容、K8s 原生部署支持使其能平滑融入云原生服務(wù)網(wǎng)格的限流體系。部署時(shí)只需記住三個(gè)關(guān)鍵點(diǎn)規(guī)則文件路徑必填、gRPC 默認(rèn)端口 10245、Envoy 側(cè) domain 必須與規(guī)則文件中的 domain 保持一致。贊分享后端微服務(wù)【免費(fèi)下載鏈接】SentinelA powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服務(wù)的高可用流控防護(hù)組件)項(xiàng)目地址https://gitcode.com/gh_mirrors/sentine/Sentinel點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Envoy 全局限流實(shí)戰(zhàn)RLS 與 RLQS 兩類 Rate Limit 服務(wù)的配置與實(shí)現(xiàn)解析Envoy 全局限流實(shí)戰(zhàn)RLS 與 RLQS 兩類 Rate Limit 服務(wù)的配置與實(shí)現(xiàn)解析 本文基于 Envoy 官方文檔 rate_limit.rst云原生服務(wù)網(wǎng)格網(wǎng)絡(luò)微服務(wù)Envoy 本地限流全解基于 Token Bucket 的 L4 連接與 HTTP 請(qǐng)求限流機(jī)制Envoy 本地限流全解基于 Token Bucket 的 L4 連接與 HTTP 請(qǐng)求限流機(jī)制 Envoy 在本地非分布式限流方面提供了三層實(shí)現(xiàn)面向云原生服務(wù)網(wǎng)格網(wǎng)絡(luò)微服務(wù)Cilium gRPC Ingress 實(shí)戰(zhàn)基于 Envoy L7 代理的 gRPC 流量路由配置與驗(yàn)證Cilium gRPC Ingress 實(shí)戰(zhàn)基于 Envoy L7 代理的 gRPC 流量路由配置與驗(yàn)證 本篇指南圍繞 Cilium 官方的 gRPC Ing云原生網(wǎng)絡(luò)服務(wù)網(wǎng)格可觀測(cè)性網(wǎng)絡(luò)安全eBPF上一篇終極磁盤健康監(jiān)控指南如何用smartmontools保護(hù)你的數(shù)據(jù)安全下一篇革命性MEV框架Artemis用Rust構(gòu)建高性能套利機(jī)器人的終極指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考