微服務限流
流量控制簡介
流量控制在網絡傳輸中是一個常用的概念,它用於調整網絡包的發送數據。在網絡傳輸時,任意時間到來的請求往往是隨機不可控的,而系統的處理能力是有的。我們需要根據系統的處理能力對流量進行控制。
熔斷降級簡介
在調用系統的時候,如果調用鏈路中的某個資源出現了不穩定,最終會導致請求發生堆積,如下圖:
而熔斷降級就可以解決這個問題,所謂的熔斷降級就是當檢測到調用鏈路中某個資源出現不穩定的表現,例如請求響應時間長或異常比例升高的時候,則對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯故障。
流量控制&熔斷降級實現方案
Hystrix
主頁地址:https://github.com/Netflix/Hystrix/
Hystrix源自Netflix API團隊於2011年開始的彈性工程工作。2012年,Hystrix不斷發展和成熟,Netflix內的許多團隊都采用了它。如今,每天在Netflix上通過Hystrix執行數以千億計的線程隔離和數以千計的信號隔離調用。這大大提高了正常運行時間和彈性。
Resilience4j
主頁地址:https://github.com/resilience4j/resilience4j
Resilience4j是受Netflix Hystrix啟發的輕量級容錯庫,但專為Java 8和函數式編程而設計。輕巧,因為該庫僅使用Vavr,而Vavr沒有任何其他外部庫依賴項。相比之下,Netflix Hystrix對Archaius具有編譯依賴性,而Archaius具有更多外部庫依賴性。
Sentinel
主頁地址:https://github.com/alibaba/Sentinel
Sentinel 是阿里巴巴出品的面向分布式服務架構的輕量級流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護等多個維度來保障微服務的穩定性。
競品對比
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔離策略 | 信號量隔離(並發線程數隔離) | 線程池隔離/信號量隔離 | 信號量隔離 |
熔斷降級策略 | 基於響應時間、異常比率、異常數 | 基於異常比率 | 基於異常比率、響應時間 |
實時統計實現 | 滑動窗口 | 滑動窗口 | Ring Bit Buffer |
動態規則配置 | 支持多種數據源 | 支持多種數據源 | 有限支持 |
擴展性 | 多個擴展點 | 插件的形式 | 接口的形式 |
基於注解的支持 | 支持 | 支持 | 支持 |
限流 | 基於 QPS,支持基於調用關系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持預熱模式、勻速器模式、預熱排隊模式 | 不支持 | 簡單的 Rate Limiter 模式 |
系統自適應保護 | 支持 | 不支持 | 不支持 |
控制台 | 提供開箱即用的控制台,可配置規則、查看秒級監控、機器發現等 | 簡單的監控查看 | 不提供控制台,可對接其它監控系統 |
Sentinel介紹
Sentinel簡介
Sentinel概述
Sentinel 是阿里巴巴出品的面向分布式服務架構的輕量級流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護等多個維度來保障微服務的穩定性。
主頁地址:https://github.com/alibaba/Sentinel
Sentinel組成
Sentinel 的使用主要分為兩個部分:
- 核心庫:主要指Java 客戶端,不依賴任何框架/庫,能夠運行於 Java 7 及以上的版本的運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持。
- 控制台:控制台主要負責管理推送規則、監控、集群限流分配管理、機器發現等。
Sentinel特征
Sentinel 具有以下特征:
- 豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的范圍)、消息削峰填谷、集群流量控制、實時熔斷下游不可用應用等。
- 完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制台中看到接入應用的單台機器秒級數據,甚至 500 台以下規模的集群的匯總運行情況。
- 廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
- 完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定制邏輯。例如定制規則管理、適配動態數據源等。
Sentinel特性
Sentinel的相關概念
資源
資源是 Sentinel 的關鍵概念。它可以是 Java 應用程序中的任何內容,例如,由應用程序提供的服務,或由應用程序調用的其它應用提供的服務,甚至可以是一段代碼。只要通過 Sentinel API 定義的代碼,就是資源,能夠被 Sentinel 保護起來。大部分情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名來標示資源。
規則
規則指的是圍繞資源的實時狀態設定的規則,可以包括流量控制規則、熔斷降級規則以及系統保護規則。所有規則可以動態實時調整。
Sentinel的優勢
- 友好的控制面板
- 支持實時監控。
- 支持多種限流。支持QPS限流,線程數限流以及多種限流策略。
- 支持多種降級模式,支持按平均返回時間降級,按多種異常數降級,按異常比率降級等。
- 方便擴展開發,支持SPI模式對chain進行擴展。
- 支持鏈路的關聯,可以實現按鏈路統計限流,系統保護,熱門資源保護等等。
流量控制實現
Sentinel 的所有規則都可以在內存態中動態地查詢及修改,修改之后立即生效。同時 Sentinel 也提供相關 API,供您來定制自己的規則策略。
Sentinel 主要支持以下幾種規則:
- 流量控制規則
- 熔斷降級規則
- 系統保護規則
- 來源訪問控制規則
- 動態規則擴展
流量控制規則實現
流量控制(flow control),其原理是監控應用流量的 QPS 或並發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。
流量控制主要有兩種方式
- 並發線程數:並發線程數限流用於保護業務線程數不被耗盡
- QPS:當 QPS 超過某個閾值的時候,則采取措施進行流量控制
一條限流規則主要由下面幾個因素組成,我們可以組合這些元素來實現不同的限流效果:
resource
:資源名,即限流規則的作用對象count
: 限流閾值grade
: 限流閾值類型(QPS 或並發線程數)limitApp
: 流控針對的調用來源,若為default
則不區分調用來源strategy
: 調用關系限流策略controlBehavior
: 流量控制效果(直接拒絕、Warm Up、勻速排隊)- 直接拒絕(
RuleConstant.CONTROL_BEHAVIOR_DEFAULT
)方式是默認的流量控制方式,當QPS超過任意規則的閾值后,新的請求就會被立即拒絕,拒絕方式為拋出FlowException
。這種方式適用於對系統處理能力確切已知的情況下,比如通過壓測確定了系統的准確水位時。 - Warm Up(
RuleConstant.CONTROL_BEHAVIOR_WARM_UP
)方式,即預熱/冷啟動方式。當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。 - 排隊等待(
RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER
)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。
- 直接拒絕(
同一個資源可以同時有多個限流規則,檢查規則時會依次檢查。
熔斷降級實現
熔斷降級會在調用鏈路中某個資源出現不穩定狀態時(例如調用超時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤。當資源被降級后,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行為是拋出 DegradeException
)。
重要的屬性
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名,即限流規則的作用對象 | |
count | 閾值 | |
grade | 熔斷策略,支持秒級 RT/秒級異常比例/分鍾級異常數 | 秒級平均 RT |
timeWindow | 降級的時間,單位為 s | |
rtSlowRequestAmount | RT 模式下 1 秒內連續多少個請求的平均 RT 超出閾值方可觸發熔斷(1.7.0 引入) | 5 |
minRequestAmount | 異常熔斷的觸發最小請求數,請求數小於該值時即使異常比率超出閾值也不會熔斷(1.7.0 引入) | 5 |
同一個資源可以同時有多個降級規則。
熔斷策略詳解:
- 平均響應時間 (DEGRADE_GRADE_RT):當 1s 內持續進入 N 個請求,對應時刻的平均響應時間(秒級)均超過閾值(count,以 ms 為單位),那么在接下的時間(DegradeRule 中的 timeWindow,以 s 為單位)之內,對這個方法的調用都會自動地熔斷(拋出 DegradeException)。
- 異常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):當資源的每秒請求量 >= N(可配置),並且每秒異常總數占通過量的比值超過閾值(DegradeRule 中的 count)之后,資源進入降級狀態,即在接下的時間(DegradeRule 中的 timeWindow,以 s 為單位)之內,對這個方法的調用都會自動地返回。異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%。
- 異常數 (DEGRADE_GRADE_EXCEPTION_COUNT):當資源近 1 分鍾的異常數目超過閾值之后會進行熔斷。注意由於統計時間是分鍾級別的,若 timeWindow小於 60s,則結束熔斷狀態后仍可能再進入熔斷狀態。
這里演示如何使用平均響應時間(DEGRADE_GRADE_RT)配置規則
實現步驟
熔斷降級規則設置有兩種方式
- 本地代碼設置
- 在Sentinel控制台動態設置
系統自適應保護實現
Sentinel 系統自適應限流從整體維度對應用入口流量進行控制,結合應用的 Load、CPU 使用率、總體平均 RT、入口 QPS 和並發線程數等幾個維度的監控指標,通過自適應的流控策略,讓系統的入口流量和系統的負載達到一個平衡,讓系統盡可能保持最大吞吐量的同時保證系統整體的穩定性。
系統保護規則是應用整體維度的,而不是資源維度的,並且僅對入口流量生效。入口流量指的是進入應用的流量(EntryType.IN),比如 Web 服務或 Dubbo 服務端接收的請求,都屬於入口流量。
系統規則支持以下的模式
- Load 自適應(僅對 Linux/Unix-like 機器生效):系統的 load1 作為啟發指標,進行自適應系統保護。當系統 load1 超過設定的啟發值,且系統當前的並發線程數超過估算的系統容量時才會觸發系統保護(BBR 階段)。系統容量由系統的
maxQps * minRt
估算得出。設定參考值一般是CPU cores * 2.5
。 - CPU usage(1.5.0+ 版本):當系統 CPU 使用率超過閾值即觸發系統保護(取值范圍 0.0-1.0),比較靈敏。
- 平均 RT:當單台機器上所有入口流量的平均 RT 達到閾值即觸發系統保護,單位是毫秒。
- 並發線程數:當單台機器上所有入口流量的並發線程數達到閾值即觸發系統保護。
- 入口 QPS:當單台機器上所有入口流量的 QPS 達到閾值即觸發系統保護。
重要的屬性
Field | 說明 | 默認值 |
---|---|---|
highestSystemLoad | load1 觸發值,用於觸發自適應控制階段 |
-1 (不生效) |
avgRt | 所有入口流量的平均響應時間 | -1 (不生效) |
maxThread | 入口流量的最大並發數 | -1 (不生效) |
qps | 所有入口資源的 QPS | -1 (不生效) |
highestCpuUsage | 當前系統的 CPU 使用率(0.0-1.0) | -1 (不生效) |
注意系統規則只針對入口資源(EntryType=IN)生效。
這里演示如何使用所有入口資源的QPS配置規則
實現步驟
系統自適應保護規則設置有兩種方式
- 本地代碼設置
- 在Sentinel控制台動態設置
授權控制實現
很多時候,我們需要根據調用來源來判斷該次請求是否允許放行,這時候可以使用 Sentinel 的來源訪問控制(黑白名單控制)的功能。來源訪問控制根據資源的請求來源(origin)判斷資源訪問是否通過,若配置白名單則只有請求來源位於白名單內時才可通過;若配置黑名單則請求來源位於黑名單時不通過,其余的請求通過。
重要的屬性
來源訪問控制規則(AuthorityRule)非常簡單,主要有以下配置項:
resource
:資源名,即限流規則的作用對象。limitApp
:請求來源,對應的黑名單/白名單,多個用","分隔,如 appA,appB。strategy
:限制模式,AUTHORITY_WHITE為白名單模式,AUTHORITY_BLACK為黑名單模式,默認為白名單模式。
這里演示實現Ip地址白名單和黑名單配置規則
實現步驟
授權控制規則設置有兩種方式
- 本地代碼設置
- 在Sentinel控制台動態設置
動態規則擴展實現
前面不管是通過Java代碼還是通過Sentinel控制台的方式去設置限流規則,都屬於手動方式,不夠靈活。這種方式一般僅用於測試和演示,生產環境上一般通過動態規則源的方式來動態管理限流規則。也就是說,很多時候限流規則會被存儲在文件、數據庫或者配置中心當中。Sentinel的DataSource
接口給我們提供了對接任意配置源的能力。
官方推薦通過控制台設置規則后將規則推送到統一的規則管理中心,客戶端實現 ReadableDataSource
接口端監聽規則中心實時獲取變更,流程如下:
常見的實現方式有:
- 拉取式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則管理中心可以是文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;實現拉模式的數據源最簡單的方式是繼承
AutoRefreshDataSource
抽象類,然后實現readSource()
方法,在該方法里從指定數據源讀取字符串格式的配置數據。 - 推送式:規則管理中心統一推送,客戶端通過注冊監聽器的方式時刻監聽變化,比如使用 Zookeeper 、Apollo等作為規則管理中心。這種方式有更好的實時性和一致性保證。實現推模式的數據源最簡單的方式是繼承
AbstractDataSource
抽象類,在其構造方法中添加監聽器,並實現readSource()
從指定數據源讀取字符串格式的配置數據。
Sentinel原理
Sentinel主要功能設計理念
流量控制
流量控制在網絡傳輸中是一個常用的概念,它用於調整網絡包的發送數據。然而,從系統穩定性角度考慮,在處理請求的速度上,也有非常多的講究。任意時間到來的請求往往是隨機不可控的,而系統的處理能力是有限的。我們需要根據系統的處理能力對流量進行控制。Sentinel 作為一個調配器,可以根據需要把隨機的請求調整成合適的形狀,如下圖所示:
流量控制設計理念
流量控制有以下幾個角度:
- 資源的調用關系,例如資源的調用鏈路,資源和資源之間的關系;
- 運行指標,例如 QPS、線程池、系統負載等;
- 控制的效果,例如直接限流、冷啟動、排隊等。
Sentinel 的設計理念是讓您自由選擇控制的角度,並進行靈活組合,從而達到想要的效果。
熔斷降級
除了流量控制以外,及時對調用鏈路中的不穩定因素進行熔斷也是 Sentinel 的使命之一。由於調用關系的復雜性,如果調用鏈路中的某個資源出現了不穩定,可能會導致請求發生堆積,進而導致級聯錯誤。
Sentinel 和 Hystrix 的原則是一致的: 當檢測到調用鏈路中某個資源出現不穩定的表現,例如請求響應時間長或異常比例升高的時候,則對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯故障。
熔斷降級設計理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一樣的方法。
Hystrix 通過線程池隔離的方式,來對依賴(在 Sentinel 的概念中對應資源)進行了隔離。這樣做的好處是資源和資源之間做到了最徹底的隔離。缺點是除了增加了線程切換的成本(過多的線程池導致線程數目過多),還需要預先給各個資源做線程池大小的分配。
Sentinel 對這個問題采取了兩種手段:
- 通過並發線程數進行限制
和資源池隔離的方法不同,Sentinel 通過限制資源並發線程的數量,來減少不穩定資源對其它資源的影響。這樣不但沒有線程切換的損耗,也不需要您預先分配線程池的大小。當某個資源出現不穩定的情況下,例如響應時間變長,對資源的直接影響就是會造成線程數的逐步堆積。當線程數在特定資源上堆積到一定的數量之后,對該資源的新請求就會被拒絕。堆積的線程完成任務后才開始繼續接收請求。
- 通過響應時間對資源進行降級
除了對並發線程數進行控制以外,Sentinel 還可以通過響應時間來快速降級不穩定的資源。當依賴的資源出現響應時間過長后,所有對該資源的訪問都會被直接拒絕,直到過了指定的時間窗口之后才重新恢復。
系統負載保護
Sentinel 同時提供系統維度的自適應保護能力。防止雪崩,是系統防護中重要的一環。當系統負載較高的時候,如果還持續讓請求進入,可能會導致系統崩潰,無法響應。在集群環境下,網絡負載均衡會把本應這台機器承載的流量轉發到其它的機器上去。如果這個時候其它的機器也處在一個邊緣狀態的時候,這個增加的流量就會導致這台機器也崩潰,最后導致整個集群不可用。
針對這個情況,Sentinel 提供了對應的保護機制,讓系統的入口流量和系統的負載達到一個平衡,保證系統在能力范圍之內處理最多的請求。
Sentinel的工作機制
Sentinel 的主要工作機制如下:
- 對主流框架提供適配或者顯示的 API,來定義需要保護的資源,並提供設施對資源進行實時統計和調用鏈路分析。
- 根據預設的規則,結合對資源的實時統計信息,對流量進行控制。同時,Sentinel 提供開放的接口,方便您定義及改變規則。
- Sentinel 提供實時的監控系統,方便您快速了解目前系統的狀態。
Hystrix
雪崩效應
在微服務架構中,一個請求需要調用多個服務是非常常見的。如客戶端訪問A服務,而A服務需要調用B服務,B服務需要調用C服務,由於網絡原因或者自身的原因,如果B服務或者C服務不能及時響應,A服務將處於阻塞狀態,直到B服務C服務響應。此時若有大量的請求涌入,容器的線程資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,造成連鎖反應,會對整個微服務系統造成災難性的嚴重后果,這就是服務故障的“雪崩”效應。
雪崩是系統中的蝴蝶效應導致其發生的原因多種多樣,有不合理的容量設計,或者是高並發下某一個方法響應變慢,亦或是某台機器的資源耗盡。從源頭上我們無法完全杜絕雪崩源頭的發生,但是雪崩的根本原因來源於服務之間的強依賴,所以我們可以提前評估,做好熔斷,隔離,限流。
服務隔離
顧名思義,它是指將系統按照一定的原則划分為若干個服務模塊,各個模塊之間相對獨立,無強依賴。當有故障發生時,能將問題和影響隔離在某個模塊內部,而不擴散風險,不波及其它模塊,不影響整體的系統服務。
熔斷降級
熔斷這一概念來源於電子工程中的斷路器(Circuit Breaker)。在互聯網系統中,當下游服務因訪問壓力過大而響應變慢或失敗,上游服務為了保護系統整體的可用性,可以暫時切斷對下游服務的調用。這種犧牲局部,保全整體的措施就叫做熔斷。
所謂降級,就是當某個服務熔斷之后,服務器將不再被調用,此時客戶端可以自己准備一個本地的fallback回調,返回一個缺省值。 也可以理解為兜底。
服務限流
限流可以認為服務降級的一種,限流就是限制系統的輸入和輸出流量已達到保護系統的目的。一般來說系統的吞吐量是可以被測算的,為了保證系統的穩固運行,一旦達到的需要限制的閾值,就需要限制流量並采取少量措施以完成限制流量的目的。比方:推遲解決,拒絕解決,或者者部分拒絕解決等等。
Hystrix介紹
Hystrix 是由Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提升系統的可用性與容錯性。Hystrix主要通過以下幾點實現延遲和容錯。
包裹請求:使用 HystrixCommand包裹對依賴的調用邏輯,每個命令在獨立線程中執行。這使用了設計模式中的“命令模式”。
跳閘機制:當某服務的錯誤率超過一定的閾值時, Hystrix可以自動或手動跳閘,停止請求該服務一段時間。
資源隔離: Hystrix為每個依賴都維護了一個小型的線程池(或者信號量)。如果該線程池已滿,發往該依賴的請求就被立即拒絕,而不是排隊等待,從而加速失敗判定。
監控: Hystrix可以近乎實時地監控運行指標和配置的變化,例如成功、失敗、超時、以及被拒絕的請求等。
回退機制:當請求失敗、超時、被拒絕,或當斷路器打開時,執行回退邏輯。回退邏輯由開發人員自行提供,例如返回一個缺省值。
自我修復:斷路器打開一段時間后,會自動進入 “半開”狀態。
熔斷器的狀態
熔斷器有三個狀態 CLOSED 、 OPEN 、 HALF_OPEN 熔斷器默認關閉狀態,當觸發熔斷后狀態變更為OPEN ,在等待到指定的時間,Hystrix會放請求檢測服務是否開啟,這期間熔斷器會變為 HALF_OPEN 半開啟狀態,熔斷探測服務可用則繼續變更為 CLOSED 關閉熔斷器。
Closed :關閉狀態(斷路器關閉),所有請求都正常訪問。代理類維護了最近調用失敗的次數,如果某次調用失敗,則使失敗次數加1。如果最近失敗次數超過了在給定時間內允許失敗的閾值,則代理類切換到斷開(Open)狀態。此時代理開啟了一個超時時鍾,當該時鍾超過了該時間,則切換到半斷開(Half-Open)狀態。該超時時間的設定是給了系統一次機會來修正導致調用失敗的錯誤。
Open :打開狀態(斷路器打開),所有請求都會被降級。Hystix會對請求情況計數,當一定時間內失敗請求百分比達到閾值,則觸發熔斷,斷路器會完全關閉。默認失敗比例的閾值是50%,請求次數最少不低於20次。
Half Open :半開狀態,open狀態不是永久的,打開后會進入休眠時間(默認是5S)。隨后斷路器會自動進入半開狀態。此時會釋放1次請求通過,若這個請求是健康的,則會關閉斷路器,否則繼續保持打開,再次進行5秒休眠計時。
熔斷器的隔離策略
微服務使用Hystrix熔斷器實現了服務的自動降級,讓微服務具備自我保護的能力,提升了系統的穩定性,也較好的解決雪崩效應。其使用方式目前支持兩種策略:
- 線程池隔離策略: 使用一個線程池來存儲當前的請求,線程池對請求作處理,設置任務返回處理超時時間,堆積的請求堆積入線程池隊列。這種方式需要為每個依賴的服務申請線程池,有一定的資源消耗,好處是可以應對突發流量(流量洪峰來臨時,處理不完可將數據存儲到線程池隊里慢慢處理)
- 信號量隔離策略: 使用一個原子計數器(或信號量)來記錄當前有多少個線程在運行,請求來先判斷計數器的數值,若超過設置的最大線程個數則丟棄改類型的新請求,若不超過則執行計數操作請求來計數器+1,請求返回計數器-1。這種方式是嚴格的控制線程且立即返回模式,無法應對突發流量(流量洪峰來臨時,處理的線程超過數量,其他的請求會直接返回,不繼續去請求依賴的服務)
Hystrix的核心源碼
Hystrix 底層基於 RxJava,RxJava 是響應式編程開發庫,因此Hystrix的整個實現策略簡單說即:把一個HystrixCommand封裝成一個Observable(待觀察者),針對自身要實現的核心功能,對Observable進行各種裝飾,並在訂閱各步裝飾的Observable,以便在指定事件到達時,添加自己的業務。
Hystrix 主要有4種調用方式:
- toObservable() 方法 :未做訂閱,只是返回一個Observable 。
- observe() 方法 :調用 #toObservable() 方法,並向 Observable 注冊 rx.subjects.ReplaySubject發起訂閱。
- queue() 方法 :調用 #toObservable() 方法的基礎上,調用:Observable#toBlocking() 和BlockingObservable#toFuture() 返回 Future 對象
- execute() 方法 :調用 #queue() 方法的基礎上,調用 Future#get() 方法,同步返回 #run() 的執行結果。
主要的執行邏輯:
-
每次調用創建一個新的HystrixCommand,把依賴調用封裝在run()方法中.
-
執行execute()/queue做同步或異步調用.
-
判斷熔斷器(circuit-breaker)是否打開,如果打開跳到步驟8,進行降級策略,如果關閉進入步驟.
4 . 判斷線程池/隊列/信號量是否跑滿,如果跑滿進入降級步驟8,否則繼續后續步驟.
-
調用HystrixCommand的run方法.運行依賴邏輯,依賴邏輯調用超時,進入步驟8.
-
判斷邏輯是否調用成功。返回成功調用結果;調用出錯,進入步驟8.
-
計算熔斷器狀態,所有的運行狀態(成功, 失敗, 拒絕,超時)上報給熔斷器,用於統計從而判斷熔斷器狀態.
-
getFallback()降級邏輯。以下四種情況將觸發getFallback調用:
-
run()方法拋出非HystrixBadRequestException異常。
-
run()方法調用超時
-
熔斷器開啟攔截調用
-
線程池/隊列/信號量是否跑滿
-
沒有實現getFallback的Command將直接拋出異常,fallback降級邏輯調用成功直接返回,降級邏輯調用失敗拋出異常.
-
返回執行成功結果
限流
(1) 計數器
計數器限流算法是最簡單的一種限流實現方式。其本質是通過維護一個單位時間內的計數器,每次請求計數器加1,當單位時間內計數器累加到大於設定的閾值,則之后的請求都被拒絕,直到單位時間已經過去,再將計數器重置為零

( 2) 漏桶算法
漏桶算法可以很好地限制容量池的大小,從而防止流量暴增。漏桶可以看作是一個帶有常量服務時間的單服務器隊列,如果漏桶(包緩存)溢出,那么數據包會被丟棄。 在網絡中,漏桶算法可以控制端口的流量輸出速率,平滑網絡上的突發流量,實現流量整形,從而為網絡提供一個穩定的流量。

為了更好的控制流量,漏桶算法需要通過兩個變量進行控制:一個是桶的大小,支持流量突發增多時可以存多少的水(burst),另一個是水桶漏洞的大小(rate)。
( 3) 令牌桶算法
令牌桶算法是對漏桶算法的一種改進,桶算法能夠限制請求調用的速率,而令牌桶算法能夠在限制調用的平均速率的同時還允許一定程度的突發調用。在令牌桶算法中,存在一個桶,用來存放固定數量的令牌。算法中存在一種機制,以一定的速率往桶中放令牌。每次請求調用需要先獲取令牌,只有拿到令牌,才有機會繼續執行,否則選擇選擇等待可用的令牌、或者直接拒絕。放令牌這個動作是持續不斷的進行,如果桶中令牌數達到上限,就丟棄令牌,所以就存在這種情況,桶中一直有大量的可用令牌,這時進來的請求就可以直接拿到令牌執行,比如設置qps為100,那么限流器初始化完成一秒后,桶中就已經有100個令牌了,這時服務還沒完全啟動好,等啟動完成對外提供服務時,該限流器可以抵擋瞬時的100個請求。所以,只有桶中沒有令牌時,請求才會進行等待,最后相當於以一定的速率執行。
在Wikipedia上,令牌桶算法是這么描述的:
1、每過1/r秒桶中增加一個令牌。
2、桶中最多存放b個令牌,如果桶滿了,新放入的令牌會被丟棄。
3、當一個n字節的數據包到達時,消耗n個令牌,然后發送該數據包。
4、如果桶中可用令牌小於n,則該數據包將被緩存或丟棄。