斷路器Netflix OSS Hystrix和Istio的Envoy比較
當我們構建微服務架構時,我們總會通過網路進行更多的呼叫。但是構建冗餘、彈性的分散式系統是一個難題,它需要一個智慧的、應用程式感知的負載平衡。ofollow,noindex" target="_blank">Matt Klein 最近寫了一篇關於現代負載平衡的精彩文章 ,你現在閱讀一下。
斷路器模式是建設大型的、有彈性的分散式系統的一個重要模式,斷路是智慧、應用程式感知負載平衡的子集功能。您要麼明確地進行負載平衡,要麼讓它隱式悄悄發生(裝作不知道)。
斷路
我們使用斷路功能來幫助防止部分或全部級聯故障,我們希望控制/減少/消除不健康系統的流量。也許我們重試的次數越多,我們對該系統施加的壓力就越大,我們是否讓它進一步降級?在一段時間內,我們可能決定進行“快速失敗”並且不允許任何呼叫。斷路器模式迫使我們必須處理我們的網路呼叫可能並且確實會發生失敗的事實,並幫助保護整個系統免於級聯故障。它關注的是感知系統元件的健康狀況以及我們是否應該將流量路由到它們。
Netflix OSS 於2012年釋出了一款 名為Netflix OSS Hystrix的 [url=https://medium.com/netflix-techblog/introducing-hystrix-for-resilience-engineering-13531c1ab362]斷路器實施方案[/url]。Hystrix是一個客戶端Java庫,用於獲取斷路行為。Hystrix 提供以下行為 。
- 自定義回退方法。
- 失敗沉默 - 在這種情況下,回退方法只返回一個空值,如果被呼叫的服務提供的資料對於將被髮送回請求客戶端的響應是可選的,這將非常有用。
- 快速失敗 - 用於需要資料或沒有良好回退並導致客戶端獲得5xx響應的情況。這可能會對裝置使用者體驗產生負面影響,這並不理想,但它可以使API伺服器保持健康狀態,並使系統能夠在故障服務再次可用時快速恢復。
Hystrix非常明顯地表示,為了斷路,故障發生時,故障/超時也沒有區別。也就是說,它可能發生在傳輸中或客戶端程式碼本身中。無論故障發生在何處,Hystrix都會檢測斷路閾值。
最後,正如我之前提到的:斷路實際上只是智慧,應用感知負載平衡的一個特殊功能。在Netflix OSS生態系統中,您還可以將Hystrix與Netflix OSS Ribbon 配對,後者是另一個用於執行客戶端負載平衡的應用程式庫。
服務網格的演變
隨著您的服務架構變得更加異構,您會發現將服務實現限制到特定的庫,框架甚至Java語言都是很困難(或不切實際)。隨著服務網路的發展,我們看到一些彈性模式,如斷路,在基礎設施中作為語言/框架獨立的解決方案實現。
服務網格可能依賴於其“資料面板”中的不同L7(應用級別)代理來實現彈性功能,如重試,超時,斷路器等。
Envoy將斷路功能視為負載平衡和執行狀況檢查的子集。Envoy 將路由功能從到後端的通訊中獨立出來,這是一個重要的考慮因素,也是讓Envoy超越其他負載均衡器粗粒度彈性的原因。Envoy可能有許多不同的“路由”,試圖將流量對映到適當的後端。這些後端被描述為“叢集”,每個叢集可以擁有自己的特定於叢集的配置以進行負載平衡。每個叢集還可以擁有自己的配置,用於被動健康檢查(異常值檢測)。
我們可以像這樣定義一個出站叢集:
<font>"clusters"</font><font>: [ { </font><font>"name"</font><font>: </font><font>"httpbin_service"</font><font>, </font><font>"connect_timeout_ms"</font><font>: 5000, </font><font>"type"</font><font>: </font><font>"static"</font><font>, </font><font>"lb_type"</font><font>: </font><font>"round_robin"</font><font>, </font><font>"hosts"</font><font>: [ { </font><font>"url"</font><font>: </font><font>"tcp://172.17.0.2:8080"</font><font> },{ </font><font>"url"</font><font>: </font><font>"tcp://172.17.0.3:8080"</font><font> } ], </font>
我們可以在這個例子中看到我們有一個名為的叢集httpbin_service,我們將使用round_robin負載平衡,我們將平衡兩個主機。
讓我們新增Envoy的斷路器配置 :
<font>"circuit_breakers"</font><font>: { </font><font>"default"</font><font>: { </font><font>"max_connections"</font><font>: 1, </font><font>"max_pending_requests"</font><font>: 1, </font><font>"max_retries"</font><font>: 3 } </font>
這裡我們的目標是HTTP 1.x工作負載。我們將出站連線數限制1,最大掛起請求數1,我們還定義了最大重試次數。在某些方面,限制請求的連線池和數量的這種行為類似於Netflix Hystrix 提供的 bulkhead 功能,如果我們的應用程式打開了比這些設定更多的連線(實際上有一些餘地 - 這些不是硬限制),Envoy將開啟斷路,並在其統計中報告這些事件,請參閱此博文詳細介紹
異常值檢測
到目前為止,我們看到Envoy所謂的“斷路器”實際上更接近connection-pool bulkheads ,為了實現“斷路”行為,Envoy做了一個叫做離群檢測的 事情。Envoy會在特定群集的負載平衡池中保留有關不同端點的操作的統計資訊。如果檢測到異常行為,則可以從負載平衡池中排除該端點。
我們來看一下異常值檢測 的示例配置:
<font>"outlier_detection"</font><font> : { </font><font>"consecutive_5xx"</font><font>: 1, </font><font>"max_ejection_percent"</font><font>: 100, </font><font>"interval_ms"</font><font>: 1000, </font><font>"base_ejection_time_ms"</font><font>: 60000 } </font>
此配置在我們與上游主機的通訊中顯示“如果我們有1個 5xx”錯誤,我們應將其標記為不健康,並暫時將其從此群集的負載平衡池中刪除。
我們還配置max_ejection_percent為100意味著我們願意拒絕遇到故障的所有主機。此設定非常特定於環境,您需要注意配置它。理想情況下,我們希望盡一切可能路由到主機,以免引入部分或級聯故障。特使預設將設定max_ejection_percent為10。
我們還將eject基礎週期設定為6000ms。主機從負載平衡池中排除彈射的實際時間是這個“基礎”設定乘以它被彈出的次數。這使我們能夠更嚴厲地懲罰那些看起來一直不太可靠的主機。
叢集恐慌
我們還應該注意Envoy異常值檢測和負載平衡。如果通過異常檢測彈出太多主機,我們可能會達到群集全域性“恐慌”模式 ,這意味著代理將不再相信它看到的負載平衡池的執行狀況並再次開始路由到所有主機。這是一個非常強大的後備功能,在分散式系統中,您必須意識到有時您在“理論”中對世界的看法是不正確的,並且最好降級到不鼓勵更多級聯故障的模式。
另一方面,您可以控制此恐慌百分比 (預設情況下,如果超過50%的負載平衡池被彈出,Envoy會驚慌)並增加恐慌閾值(> 50%)甚至完全禁用(將其設定為0)。設定它為0會使Envoy的斷路功能之間的行為更像Netflix Hystrix 。
細粒度的斷路策略
庫包的一個好處是我們可以應用的細粒度應用感知電路中斷策略。Hystrix通常是通過一組負載均衡器的單個網路路由將提供許多不同型別的功能,在幾個不同的HyrxScript命令中。每個HyrScript命令都需要設定不同的能力:吞吐量限制、超時值和回退策略。
而對於Envoy,我們可以通過路由匹配 來完成相同的外迴路的中斷策略,指定我們想要操作哪些確切的叢集呼叫以及特定的叢集策略 。
使用Istio進行細粒度斷路
我們可以使用Istio 更高級別的配置來指定細粒度的斷路,在Istio中,我們使用DestinationPolicies 來配置負載平衡和迴路中斷策略。以下是在Istio中指定斷路功能的destiantion策略示例:
metadata: name: reviews-cb-policy namespace: <b>default</b> spec: destination: name: reviews labels: version: v1 circuitBreaker: simpleCb: maxConnections: 100 httpMaxRequests: 1000 httpMaxRequestsPerConnection: 10 httpConsecutiveErrors: 7 sleepWindow: 15m httpDetectionInterval: 5m
斷路啟用
使用Hystrix,回退的概念內置於庫中,可以由庫編排。在Hystrix中,我們可以執行快取結果,回退到預設值,甚至通過呼叫不同的服務來獲取備用路徑。我們還可以獲得有關失敗的詳細資訊,並制定特定於應用程式的決策。
使用服務網格,目前沒有用於上下文傳播故障的專用庫,故障原因更加不透明。
這並不意味著我們的應用程式無法進行回退(對於傳輸和客戶端特定的錯誤)。我認為對於任何應用程式的協議都非常重要,無論是使用特定於庫的框架還是不是使用,都要始終遵守它試圖為其客戶保留的承諾。如果它發現它無法完成其預期的操作,它應該找到一種優雅降級的方法。幸運的是,您不需要特定於應用程式的框架。大多數語言都有內建錯誤和異常捕獲和處理。應在這些異常路徑中實現回退。
概括
- 斷路是負載平衡器的特殊行為
- Hystrix只執行斷路功能; 負載均衡可以與Ribbon(或任何客戶端負載平衡庫)配對
- Hystrix將“快速失敗回退”概念作為庫包/框架的關注點,並使其成為前沿和中心
- 作為其負載平衡實施的一部分,Envoy具有斷路和異常檢測功能
- Envoy“斷路器”更像是Hystrix的bulkhead,“異常檢測”更類似於Hystrix斷路器
- Envoy擁有許多預設的生產/戰鬥力的測試功能,如恐慌閾值
- 服務網格缺乏嚮應用程式提供故障上下文的能力(請繼續關注!)