阿里 双11 同款流控降级组件 Sentinel Go 正式GA,云原生服务稳稳稳
作者 | 趙奕豪(宿何)??Sentinel 開源項目負責人
來源|阿里巴巴云原生公眾號
前言
微服務的穩定性一直是開發者非常關注的話題。隨著業務從單體架構向分布式架構演進以及部署方式的變化,服務之間的依賴關系變得越來越復雜,業務系統也面臨著巨大的高可用挑戰。
在生產環境中大家可能遇到過各種不穩定的情況,比如:
- 大促時瞬間洪峰流量導致系統超出最大負載,load 飆高,系統崩潰導致用戶無法下單。
- “黑馬”熱點商品擊穿緩存,DB 被打垮,擠占正常流量。
- 調用端被不穩定第三方服務拖垮,線程池被占滿,調用堆積,導致整個調用鏈路卡死。
這些不穩定的場景可能會導致嚴重后果,但很多時候我們又容易忽視這些與流量/依賴相關的高可用防護。大家可能想問:如何預防這些不穩定因素帶來的影響?如何針對流量進行高可用的防護?如何保障服務“穩如磐石”?這時候我們就要請出阿里雙十一同款的高可用防護中間件 —— Sentinel。在今年剛剛過去的天貓 雙11 大促中,Sentinel 完美地保障了阿里成千上萬服務 雙11 峰值流量的穩定性,同時 Sentinel Go 版本也在近期正式宣布 GA。下面我們來一起了解下 Sentinel Go 的核心場景以及社區在云原生方面的探索。
Sentinel 介紹
Sentinel?是阿里巴巴開源的,面向分布式服務架構的流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統自適應保護等多個維度來幫助開發者保障微服務的穩定性。Sentinel 承接了阿里巴巴近 10 年的 雙11 大促流量的核心場景,例如秒殺、冷啟動、消息削峰填谷、集群流量控制、實時熔斷下游不可用服務等,是保障微服務高可用的利器,原生支持 Java/Go/C++ 等多種語言,并且提供 Istio/Envoy 全局流控支持來為 Service Mesh 提供高可用防護的能力。
今年年初,Sentinel 社區宣布了 Sentinel Go 版本的發布,為 Go 語言的微服務和基礎組件提供高可用防護和容錯能力的原生支持,標志著 Sentinel 朝著多元化與云原生邁出了新的一步。在這半年的時間內,社區推出了近 10 個版本,逐步對齊了核心高可用防護和容錯能力,同時也在不斷擴充開源生態,與 dubbo-go、螞蟻 MOSN 等開源社區進行共建。
就在近期,Sentinel Go 1.0 GA 版本正式發布,標志著 Go 版本正式進入生產可用階段。Sentinel Go 1.0 版本對齊了 Java 版本核心的高可用防護和容錯能力,包括限流、流量整形、并發控制、熔斷降級、系統自適應保護、熱點防護等特性。同時 Go 版本已覆蓋主流開源生態,提供了 Gin、gRPC、go-micro、dubbo-go 等常用微服務框架的適配,并提供了 etcd、Nacos、Consul 等動態數據源擴展支持。Sentinel Go 也在朝著云原生的方向不斷演進,1.0 版本中也進行了一些云原生方面的探索,包括 Kubernetes CRD data-source, Kubernetes HPA 等。對于 Sentinel Go 版本而言,我們期望的流控場景并不局限于微服務應用本身。云原生基礎組件中 Go 語言生態占比較高,而這些云原生組件很多時候又缺乏細粒度、自適應的保護與容錯機制,這時候就可以結合組件的一些擴展機制,利用 Sentinel Go 來保護自身的穩定性。
Sentinel 底層通過高性能的滑動窗口進行秒級調用指標統計,結合 token bucket, leaky bucket 和自適應流控算法來透出核心的高可用防護能力。
那么我們如何利用 Sentinel Go 來保證我們微服務的穩定性?下面我們來看幾個典型的應用場景。
高可用防護的核心場景
1. 流量控制與調配
流量是非常隨機性的、不可預測的。前一秒可能還風平浪靜,后一秒可能就出現流量洪峰了(例如 雙11 零點的場景)。然而我們系統的容量總是有限的,如果突然而來的流量超過了系統的承受能力,就可能會導致請求處理不過來,堆積的請求處理緩慢,CPU/Load 飆高,最后導致系統崩潰。因此,我們需要針對這種突發的流量來進行限制,在盡可能處理請求的同時來保障服務不被打垮,這就是流量控制。流量控制的場景是非常通用的,像脈沖流量類的場景都是適用的。
通常在 Web 入口或服務提供方(Service Provider)的場景下,我們需要保護服務提供方自身不被流量洪峰打垮。這時候通常根據服務提供方的服務能力進行流量控制,或針對特定的服務調用方進行限制。我們可以結合前期壓測評估核心接口的承受能力,配置 QPS 模式的流控規則,當每秒的請求量超過設定的閾值時,會自動拒絕多余的請求。
下面是最簡單的一個 Sentinel 限流規則的配置示例:
_, err = flow.LoadRules([]*flow.Rule{{Resource: "some-service", // 埋點資源名Count: 10, // 閾值為 10,默認為秒級維度統計,即該請求單機每秒不超過 10 次ControlBehavior: flow.Reject, // 控制效果為直接拒絕,不控制請求之間的時間間隔,不排隊}, })2. Warm-Up 預熱流控
當系統長期處于低水位的情況下,流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。比如剛啟動的服務,數據庫連接池可能還未初始化,緩存也處于空的狀態,這時候激增的流量非常容易導致服務崩潰。如果采用傳統的限流模式,不加以平滑/削峰限制,其實也是有被打掛的風險的(比如一瞬間并發很高)。針對這種場景,我們就可以利用 Sentinel 的 Warm-Up 流控模式,控制通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,而不是在一瞬間全部放行,同時結合請求間隔控制+排隊的控制效果 來防止大量請求都在同一時刻被處理。這樣可以給冷系統一個預熱的時間,避免冷系統被壓垮。
3. 并發控制與熔斷降級
一個服務常常會調用別的模塊,可能是另外的一個遠程服務、數據庫,或者第三方 API 等。例如,支付的時候,可能需要遠程調用銀聯提供的 API;查詢某個商品的價格,可能需要進行數據庫查詢。然而,這個被依賴服務的穩定性是不能保證的。如果依賴的服務出現了不穩定的情況,請求的響應時間變長,那么調用服務的方法的響應時間也會變長,線程會產生堆積,最終可能耗盡業務自身的線程池,服務本身也變得不可用。
現代微服務架構都是分布式的,由非常多的服務組成。不同服務之間相互調用,組成復雜的調用鏈路。以上的問題在鏈路調用中會產生放大的效果。復雜鏈路上的某一環不穩定,就可能會層層級聯,最終導致整個鏈路都不可用。Sentinel Go 提供以下的能力避免慢調用等不穩定因素造成不可用:
- 并發控制(isolation 模塊):作為一種輕量級隔離的手段,控制某些調用的并發數(即正在進行的數目),防止過多的慢調用擠占正常的調用。
- 熔斷降級(circuitbreaker 模塊):對不穩定的弱依賴調用進行自動熔斷降級,暫時切斷不穩定調用,避免局部不穩定因素導致整體的雪崩。
Sentinel Go 熔斷降級特性基于熔斷器模式的思想,在服務出現不穩定因素(如響應時間變長,錯誤率上升)的時候暫時切斷服務的調用,等待一段時間再進行嘗試。一方面防止給不穩定服務“雪上加霜”,另一方面保護服務的調用方不被拖垮。Sentinel 支持兩種熔斷策略:基于響應時間(慢調用比例)和基于錯誤(錯誤比例/錯誤數),可以有效地針對各種不穩定的場景進行防護。
注意熔斷器模式一般適用于弱依賴調用,即降級后不影響業務主流程,開發者需要設計好降級后的 fallback 邏輯和返回值。另外需要注意的是,即使服務調用方引入了熔斷降級機制,我們還是需要在 HTTP 或 RPC 客戶端配置請求超時時間,來做一個兜底的防護。
4. 熱點防護
流量是隨機的,不可預測的。為了防止被大流量打垮,我們通常會對核心接口配置限流規則,但有的場景下配置普通的流控規則是不夠的。我們來看這樣一種場景——大促峰值的時候,總是會有不少“熱點”商品,這些熱點商品的瞬時訪問量非常高。一般情況下,我們可以事先預測一波熱點商品,并對這些商品信息進行緩存“預熱”,以便在出現大量訪問時可以快速返回而不會都打到 DB 上。但每次大促都會涌現出一些“黑馬”商品,這些“黑馬”商品是我們無法事先預測的,沒有被預熱。當這些“黑馬”商品訪問量激增時,大量的請求會擊穿緩存,直接打到 DB 層,導致 DB 訪問緩慢,擠占正常商品請求的資源池,最后可能會導致系統掛掉。這時候,利用 Sentinel 的熱點參數流量控制,自動識別熱點參數并控制每個熱點值的訪問 QPS 或并發量,可以有效地防止過“熱”的參數訪問擠占正常的調用資源。
再比如有的場景下我們希望限制每個用戶調用某個 API 的頻率,將 API 名稱+userId 作為埋點資源名顯然是不合適的。這時候我們可以在給 API 埋點的時候通過?WithArgs(xxx)?將 userId 作為參數傳入到 API 埋點中,然后配置熱點規則即可針對每個用戶分別限制調用頻率;同時,Sentinel 也支持針對某些具體值單獨配置限流值,進行精細化流控。像其他規則一樣,熱點流控規則同樣支持通過動態數據源進行動態配置。
Sentinel Go 提供的 RPC 框架整合模塊(如 Dubbo、gRPC)均會自動將 RPC 調用的參數列表附帶在埋點中,用戶可以直接針對相應的參數位置配置熱點流控規則。注意如果需要配置具體值限流,受類型系統限制,目前僅支持基本類型和 string 類型。
Sentinel Go 的熱點流量控制基于緩存淘汰機制+令牌桶機制實現。Sentinel 通過淘汰機制(如 LRU、LFU、ARC 策略等)來識別熱點參數,通過令牌桶機制來控制每個熱點參數的訪問量。目前的 Sentinel Go 版本采用 LRU 策略統計熱點參數,社區也已有貢獻者提交了優化淘汰機制的 PR,在后續的版本中社區會引入更多的緩存淘汰機制來適配不同的場景。
5. 系統自適應保護
有了以上的流量防護場景,是不是就萬事無憂了呢?其實不是的,很多時候我們無法事先就準確評估某個接口的準確容量,甚至無法預知核心接口的流量特征(如是否有脈沖情況),這時候靠事先配置的規則可能無法有效地保護當前服務節點;一些情況下我們可能突然發現機器的 Load 和 CPU usage 等開始飚高,但卻沒有辦法很快的確認到是什么原因造成的,也來不及處理異常。這個時候我們其實需要做的是快速止損,先通過一些自動化的兜底防護手段,將瀕臨崩潰的微服務“拉”回來。針對這些情況,Sentinel Go 提供了一種系統自適應保護規則,結合系統指標和服務容量,自適應動態調整流量。
Sentinel 系統自適應保護策略借鑒了 TCP BBR 算法的思想,結合系統的 Load、CPU 使用率以及服務的入口 QPS、響應時間和并發量等幾個維度的監控指標,通過自適應的流控策略,讓系統的入口流量和系統的負載達到一個平衡,讓系統盡可能跑在最大吞吐量的同時保證系統整體的穩定性。系統規則可以作為整個服務的一個兜底防護策略,保障服務不掛,對 CPU 密集型的場景會有比較好的效果。同時,社區也在結合自動化控制理論和強化學習等手段,持續完善自適應流控的效果和適用場景。在未來的版本中,社區會也推出更多試驗性的自適應流控策略,來滿足更多的可用性場景。
云原生探索
云原生是 Sentinel Go 版本演進最為重要的一環。在 GA 的過程中,Sentinel Go 社區也在 Kubernetes 和 Service Mesh 等場景下進行了一些探索。
1. Kubernetes CRD data-source
在生產環境中我們一般都需要通過配置中心來動態管理各種規則配置。在 Kubernetes 集群中,我們可以天然利用 Kubernetes CRD 的方式來管理應用的 Sentinel 規則。在 Go 1.0.0 版本中社區提供了基本的 Sentinel 規則 CRD 抽象以及相應的 數據源實現。用戶只需要先導入 Sentinel 規則 CRD 定義文件,接入 Sentinel 時注冊對應的 data-source,然后按照 CRD 定義的格式編寫 YAML 配置并 kubectl apply 到對應的 namespace 下即可實現動態配置規則。以下是一個流控規則的示例:
apiVersion: datasource.sentinel.io/v1alpha1 kind: FlowRules metadata:name: foo-sentinel-flow-rules spec:rules:- resource: simple-resourcethreshold: 500- resource: something-to-smooththreshold: 100controlBehavior: ThrottlingmaxQueueingTimeMs: 500- resource: something-to-warmupthreshold: 200tokenCalculateStrategy: WarmUpcontrolBehavior: RejectwarmUpPeriodSec: 30warmUpColdFactor: 3Kubernetes CRD data-source 模塊地址:https://github.com/sentinel-group/sentinel-go-datasource-k8s-crd
后續社區會進一步完善 Rule CRD 定義并與其它社區一起探討高可用防護相關的標準抽象。
2. Service Mesh
Service Mesh 是微服務向云原生演進的趨勢之一。在 Service Mesh 架構下,一些服務治理和策略控制的能力都逐漸下沉到了 data plane 層。去年 Sentinel 社區在 Java 1.7.0 版本里面做了一些嘗試,提供了 Envoy Global Rate Limiting gRPC Service 的實現 —— Sentinel RLS token server,借助 Sentinel 集群限流 token server 來為 Envoy 服務網格提供集群流量控制的能力。今年隨著 Sentinel Go 版本的誕生,社區與更多的 Service Mesh 產品開展合作、整合。我們與螞蟻的 MOSN 社區進行共建,在 MOSN Mesh 中原生支持了 Sentinel Go 的流控降級能力,同時也已在螞蟻內部落地。社區也在探索更為通用的方案,如利用 Istio 的 Envoy WASM 擴展機制實現 Sentinel 插件,讓 Istio/Envoy 服務網格可以借助 Sentinel 原生的流控降級與自適應保護的能力來保障整個集群服務的穩定性。
3. Kubernetes HPA based on Sentinel metrics
保障服務穩定性的方法多種多樣,除了各種規則對流量進行“控制”之外,“彈性”也是一種思路。對于部署在 Kubernetes 中的應用來說,可以利用 Kubernetes HPA 能力進行對服務進行水平擴縮容。HPA 默認支持多種系統指標,并且支持自定義指標統計。目前我們已經在阿里云 Kubernetes 容器服務上結合 AHAS Sentinel 支持基于服務的平均 QPS、響應時間等作為條件進行彈性伸縮。社區也正在這一塊做一些嘗試,將一些 Sentinel 的服務級別的指標統計(通過量,拒絕量,響應時間等)通過 Prometheus 或 OpenTelemetry 等標準方式透出,并適配到 Kubernetes HPA 中。
當然基于 Sentinel 的彈性方案不是萬靈藥,它只適用于一些特定的場景,比如適用于啟動速度快的無狀態服務(Serverless 場景)。對于啟動較慢的服務,或非本服務容量問題的場景(如依賴的 DB 容量不夠),彈性的方案不能很好地解決穩定性的問題,甚至可能會加劇服務的惡化。
Let's start hacking!
了解了以上的高可用防護的場景,以及 Sentinel 在云原生方向的一些探索,相信大家對微服務容錯與穩定性的手段有了新的體會。歡迎大家動手玩一下 demo,將微服務接入 Sentinel 來享受高可用防護和容錯的能力,讓服務“穩如磐石”。同時 Sentinel Go 1.0 GA 版本的發布離不開社區的貢獻,感謝所有參與貢獻的小伙伴們。
本次 GA 我們也新加入了兩位給力的 committer —— @sanxun0325 和?@luckyxiaoqiang,兩位在 1.0 版本的演進帶來了 Warm Up 流控、Nacos 動態數據源以及一系列功能改進和性能優化,非常積極地幫助社區答疑解惑以及 review 代碼。恭喜兩位!社區在未來版本中也會朝著云原生和自適應智能化的方向不斷探索和演進,也歡迎更多的同學加入貢獻小組,一起參與 Sentinel 未來的演進,創造無限可能。我們鼓勵任何形式的貢獻,包括但不限于:
- bug fix
- new features/improvements
- dashboard
- document/website
- test cases
開發者可以在 GitHub 上面的 good first issue 列表上挑選感興趣的 issue 來參與討論和貢獻。我們會重點關注積極參與貢獻的開發者,核心貢獻者會提名為 Committer,一起主導社區的發展。我們也歡迎大家有任何問題和建議,都可以通過 GitHub issue、Gitter 或釘釘群(群號:30150716)等渠道進行交流。Now start hacking!
- Sentinel Go repo:https://github.com/alibaba/sentinel-golang
- 企業用戶歡迎進行登記:https://github.com/alibaba/Sentinel/issues/18
- Sentinel 阿里云企業版:https://ahas.console.aliyun.com/
原文鏈接:https://developer.aliyun.com/article/779682?
版權聲明:本文內容由阿里云實名注冊用戶自發貢獻,版權歸原作者所有,阿里云開發者社區不擁有其著作權,亦不承擔相應法律責任。具體規則請查看《阿里云開發者社區用戶服務協議》和《阿里云開發者社區知識產權保護指引》。如果您發現本社區中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社區將立刻刪除涉嫌侵權內容。總結
以上是生活随笔為你收集整理的阿里 双11 同款流控降级组件 Sentinel Go 正式GA,云原生服务稳稳稳的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云打下AI地基,更多的开发者走向了前
- 下一篇: 如何接地气地接入微前端?