中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Hystrix提高系統可用性

發布時間:2021-11-10 17:59:49 來源:億速云 閱讀:138 作者:柒染 欄目:大數據

本篇文章給大家分享的是有關如何使用Hystrix提高系統可用性,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

今天稍微復雜點的互聯網應用,服務端基本都是分布式的,大量的服務支撐起整個系統,服務之間也難免有大量的依賴關系,依賴都是通過網絡連接起來。

然而任何一個服務的可用性都不是 100% 的,網絡亦是脆弱的。當我依賴的某個服務不可用的時候,我自身是否會被拖死?當網絡不穩定的時候,我自身是否會被拖死?這些在單機環境下不太需要考慮的問題,在分布式環境下就不得不考慮了。假設我有5個依賴的服務,他們的可用性都是99.95%,即一年不可用時間約為4個多小時,那么是否意味著我的可用性最多就是 99.95% 的5次方,99.75%(近乎一天),再加上網絡不穩定因素、依賴服務可能更多,可用性會更低。考慮到所依賴的服務必定會在某些時間不可用,考慮到網絡必定會不穩定,我們應該怎么設計自身服務?即,怎么為出錯設計?

Michael T. Nygard 在在精彩的《Release It!》一書中總結了很多提高系統可用性的模式,其中我認為非常重要的兩條是:

  1. 使用超時

  2. 使用斷路器

第一條,通過網絡調用外部依賴服務的時候,都必須應該設置超時。在健康的情況下,一般局域往的一次遠程調用在幾十毫秒內就返回了,但是當網絡擁堵的時候,或者所依賴服務不可用的時候,這個時間可能是好多秒,或者壓根就僵死了。通常情況下,一次遠程調用對應了一個線程或者進程,如果響應太慢,或者僵死了,那一個進程/線程,就被拖死,短時間內得不到釋放,而進程/線程都對應了系統資源,這就等于說我自身服務資源會被耗盡,導致自身服務不可用。假設我的服務依賴于很多服務,其中一個非核心的依賴如果不可用,而且沒有超時機制,那么這個非核心依賴就能拖死我的服務,盡管理論上即使沒有它我在大部分情況還能健康運轉的。

斷路器其實我們大家都不陌生(你會換保險絲么?),如果你家沒有斷路器,當電流過載,或者短路的時候,電路不斷開,電線就會升溫,造成火災,燒掉房子。有了斷路器之后,電流過載的時候,保險絲就會首先燒掉,斷開電路,不至于引起更大的災難(只不過這個時候你得換保險絲)。

如何使用Hystrix提高系統可用性

當我們的服務訪問某項依賴有大量超時的時候,再讓新的請求去訪問已經沒有太大意義,那只會無謂的消耗現有資源。即使你已經設置超時1秒了,那明知依賴不可用的情況下再讓更多的請求,比如100個,去訪問這個依賴,也會導致100個線程1秒的資源浪費。這個時候,斷路器就能幫助我們避免這種資源浪費,在自身服務和依賴之間放一個斷路器,實時統計訪問的狀態,當訪問超時或者失敗達到某個閾值的時候(如50%請求超時,或者連續20次請失敗),就打開斷路器,那么后續的請求就直接返回失敗,不至于浪費資源。斷路器再根據一個時間間隔(如5分鐘)嘗試關閉斷路器(或者更換保險絲),看依賴是否恢復服務了。

超時機制和斷路器能夠很好的保護我們的服務,不受依賴服務不可用的影響太大,具體可以參看文章《 使用熔斷器設計模式保護軟件》。然而具體實現這兩個模式還是有一定的復雜度的,所幸 Netflix 開源的 Hystrix框架 幫我們大大簡化了超時機制和斷路器的實現,Hystrix:供分布式系統使用,提供延遲和容錯功能,隔離遠程系統、訪問和第三方程序庫的訪問點,防止級聯失敗,保證復雜的分布系統在面臨不可避免的失敗時,仍能有其彈性。在Codeplex上有一個.NET的移植版本https://hystrixnet.codeplex.com/ 。

使用Hystrix,需要通過Command封裝對遠程依賴的調用:

public class GetCurrentTimeCommand : HystrixCommand<long>

{

private static long currentTimeCache;

public GetCurrentTimeCommand()

: base(HystrixCommandSetter.WithGroupKey("TimeGroup")

.AndCommandKey("GetCurrentTime")

.AndCommandPropertiesDefaults(new HystrixCommandPropertiesSetter().WithExecutionIsolationThreadTimeout(TimeSpan.FromSeconds(1.0)).WithExecutionIsolationThreadInterruptOnTimeout(true)))

{

}

protected override long Run()

{

using (WebClient wc = new WebClient())

{

string content = wc.DownloadString("http://tycho.usno.navy.mil/cgi-bin/time.pl");

XDocument document = XDocument.Parse(content);

currentTimeCache = long.Parse(document.Element("usno").Element("t").Value);

return currentTimeCache;

}

}

protected override long GetFallback()

{

return currentTimeCache;

}

}

然后在需要的時候調用這個Command:

GetCurrentTimeCommand command = new GetCurrentTimeCommand();

long currentTime = command.Execute();

上述是同步調用,當然如果業務邏輯允許且更追求性能,或許可以選擇異步調用:

該例中,不論 WebClient. DownloadString () 自身有沒有超時機制(可能你會發現很多遠程調用接口自身并沒有給你提供超時機制),用 HystrixCommand 封裝過后,超時是強制的,默認超時時間是1秒,當然你可以根據需要自己在構造函數中調節 Command 的超時時間,例如說2秒:

HystrixCommandSetter.WithGroupKey("TimeGroup")

.AndCommandKey("GetCurrentTime")

.AndCommandPropertiesDefaults(new HystrixCommandPropertiesSetter().WithExecutionIsolationThreadTimeout(TimeSpan.FromSeconds(2.0)).WithExecutionIsolationThreadInterruptOnTimeout(true))

當Hystrix執行命令超時后,Hystrix 執行命令超時或者失敗之后,是會嘗試去調用一個 fallback 的,這個 fallback 即一個備用方案,要為 HystrixCommand 提供 fallback,只要重寫 protected virtual R GetFallback()方法即可。

一般情況下,Hystrix 會為 Command 分配專門的線程池,池中的線程數量是固定的,這也是一個保護機制,假設你依賴很多個服務,你不希望對其中一個服務的調用消耗過多的線程以致于其他服務都沒線程調用了。默認這個線程池的大小是10,即并發執行的命令最多只能有是個了,超過這個數量的調用就得排隊,如果隊伍太長了(默認超過5),Hystrix就立刻走 fallback 或者拋異常。

根據你的具體需要,你可能會想要調整某個Command的線程池大小,例如你對某個依賴的調用平均響應時間為200ms,而峰值的QPS是200,那么這個并發至少就是 0.2 x 200 = 40 (Little's Law),考慮到一定的寬松度,這個線程池的大小設置為60可能比較合適:

public GetCurrentTimeCommand()

: base(HystrixCommandSetter.WithGroupKey("TimeGroup")

.AndCommandKey("GetCurrentTime")

.AndCommandPropertiesDefaults(new HystrixCommandPropertiesSetter().WithExecutionIsolationThreadTimeout(TimeSpan.FromSeconds(1.0)).WithExecutionIsolationThreadInterruptOnTimeout(true))

.AndThreadPoolPropertiesDefaults(new HystrixThreadPoolPropertiesSetter().WithCoreSize(60) // size of thread pool

.WithKeepAliveTime(TimeSpan.FromMinutes(1.0)) // minutes to keep a thread alive (though in practice this doesn't get used as by default we set a fixed size)

.WithMaxQueueSize(100) // size of queue (but we never allow it to grow this big ... this can't be dynamically changed so we use 'queueSizeRejectionThreshold' to artificially limit and reject)

.WithQueueSizeRejectionThreshold(10) // number of items in queue at which point we reject (this can be dyamically changed)

.WithMetricsRollingStatisticalWindow(10000) // milliseconds for rolling number

.WithMetricsRollingStatisticalWindowBuckets(10)))

{

}

說了這么多,還沒提到Hystrix的斷路器,其實對于使用者來說,斷路器機制默認是啟用的,但是編程接口默認幾乎不需要關心這個,機制和前面講的也差不多,Hystrix會統計命令調用,看其中失敗的比例,默認當超過50%失敗后,開啟斷路器,那之后一段時間的命令調用直接返回失敗(或者走fallback),5秒之后,Hystrix再嘗試關閉斷路器,看看請求是否能正常響應。下面的幾行Hystrix源碼展示了它如何統計失敗率的:

public HealthCounts GetHealthCounts()

{

// we put an interval between snapshots so high-volume commands don't

// spend too much unnecessary time calculating metrics in very small time periods

long lastTime = this.lastHealthCountsSnapshot;

long currentTime = ActualTime.CurrentTimeInMillis;

if (currentTime - lastTime >= this.properties.MetricsHealthSnapshotInterval.Get().TotalMilliseconds || this.healthCountsSnapshot == null)

{

if (Interlocked.CompareExchange(ref this.lastHealthCountsSnapshot, currentTime, lastTime) == lastTime)

{

// our thread won setting the snapshot time so we will proceed with generating a new snapshot

// losing threads will continue using the old snapshot

long success = counter.GetRollingSum(HystrixRollingNumberEvent.Success);

long failure = counter.GetRollingSum(HystrixRollingNumberEvent.Failure); // fallbacks occur on this

long timeout = counter.GetRollingSum(HystrixRollingNumberEvent.Timeout); // fallbacks occur on this

long threadPoolRejected = counter.GetRollingSum(HystrixRollingNumberEvent.ThreadPoolRejected); // fallbacks occur on this

long semaphoreRejected = counter.GetRollingSum(HystrixRollingNumberEvent.SemaphoreRejected); // fallbacks occur on this

long shortCircuited = counter.GetRollingSum(HystrixRollingNumberEvent.ShortCircuited); // fallbacks occur on this

long totalCount = failure + success + timeout + threadPoolRejected + shortCircuited + semaphoreRejected;

long errorCount = failure + timeout + threadPoolRejected + shortCircuited + semaphoreRejected;

healthCountsSnapshot = new HealthCounts(totalCount, errorCount); }

}

return healthCountsSnapshot;

}

其中 failure 表示命令本身發生錯誤、success 自然不必說,timeout 是超時、threadPoolRejected 表示當線程池滿后拒絕的命令調用、shortCircuited 表示斷路器打開后拒絕的命令調用,semaphoreRejected 使用信號量機制(而不是線程池)拒絕的命令調用。

原文地址:http://www.cnblogs.com/shanyou/p/4752226.html


關注我們的方法:
1.點擊文章標題下的“dotNET跨平臺”藍字,或者在微信搜索“opendotnet”,加關注
2.老朋友點擊點擊右上角“……”標志分享到朋友圈

如何使用Hystrix提高系統可用性

本文分享自微信公眾號 - dotNET跨平臺(opendotnet)。
如有侵權,請聯系 support@oschina.cn 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

以上就是如何使用Hystrix提高系統可用性,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黔西县| 昌乐县| 贵定县| 磐石市| 永平县| 炉霍县| 怀集县| 太仆寺旗| 高清| 宕昌县| 大田县| 清徐县| 琼中| 蒙城县| 仁寿县| 古田县| 陇川县| 铜山县| 沂水县| 清镇市| 威宁| 安平县| 曲周县| 寻乌县| 平阴县| 宁乡县| 荔浦县| 衡东县| 武夷山市| 兴城市| 乌兰察布市| 青冈县| 克拉玛依市| 界首市| 永靖县| 吉首市| 商都县| 科技| 苍梧县| 酉阳| 博白县|