只有累積,沒有奇蹟

2019年6月10日 星期一

[NETCore] Polly 重試機制搭配 jitter 策略

Jitter 策略
上一篇 [NETCore] 使用 Polly 實現重試 (Retry) 策略 分享了使用 Polly 的重試 API 幫助我們達到重試的功能,後續在尋找相關文件時看到重試時的一種策略 Jitter strategy在高併發的情境下如果使用重試策略可能會影響到系統,若要解決用戶端因為同時間重試造成伺服器資源高峰的狀況,可以透過添加隨機時間來改善,另外在 Jitter: Making Things Better With Randomness 中也有提到此觀念
simulate synchronization emerging in previously unsynchronized systems communicating over a network. This leads to short-lived spikes in contention, and other correlated effects on the network. Their solution is to add randomness, which breaks the loop that creates synchronization.
了解了重試在高併發可能造成的原因之後,也提到了解決方法是在重試時加入隨機時間,實作上相當簡單在 C# 中使用 Random 類別就可以輕鬆達到,透過以下簡單的 sample code 讓大家更容易了解,代碼內容是在每秒發送時加入 random 0-100 毫秒的隨機時間,代碼如下
Random jitterer = new Random();

for (int i = 0; i < 6; i++)
{
    Console.WriteLine(TimeSpan.FromSeconds(1) + TimeSpan.FromMilliseconds(jitterer.Next(0, 100)));
}

Console.ReadKey();
執行後輸出內容如下,簡單實作出 jitter 策略

Jitter Library
在 Nuget 中同樣也可以發現 jitter 相關套件,這裡推薦可以使用 jitterMagic 函式庫,可以在 Visual Studio 中透過 Nuget Package Manager 下載,搜尋 jitterMagic 後選擇後點擊 install 
或者是在 Nuget Package Console 輸入下列指令
Install-Package JitterMagic
使用方式相當容易,透過  Jitter.Apply  傳入起始值或是指定百分比(預設百分比為 25%),舉例來說設定初始值為 100,得到的數字會落於 75 - 125 之間
for (int i = 0; i < 10; i++)
{
    Console.Write(Jitter.Apply(100) + ",");
}
// result : 124,85,103,115,104,111,85,78,123,122,
API 也提供指定百分比,舉例來說指定 87% 輸出如下 
for (int i = 0; i < 10; i++)
{
    Console.Write(Jitter.Apply(100, new JitterSettings(87)) + ",");
}
// result : 98,168,15,174,28,46,56,101,54,60,
在 JitterMagic API 也適用 double,詳細使用可以參考官方 GitHub 說明 : 傳送門

Polly Retry + Jitter Strategy
接著在把重點放回到重試機制,在上一篇 [NETCore] 使用 Polly 實現重試 (Retry) 策略 使用波麗鳥 Polly 進行重試機制,在與 Jitter 策略搭配後的代碼 (實作 Random 類別) 如下
Random jitterer = new Random();
Policy
     .Handle<HttpRequestException>()
     .OrResult<HttpResponseMessage>(result => result.StatusCode != HttpStatusCode.OK)
     .WaitAndRetry(5,    
         retryAttempt =>
             TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                         + TimeSpan.FromMilliseconds(jitterer.Next(0, 100))
     )
     .Execute(doMockHTTPRequest);
可以看到代碼中第 8 行中發送時間加上 jitter 策略,讓重試時間為 2 的 n 次方 (n=第幾次重試) 加上隨機時間,改善高併發時可能影起的效能問題,如果想套用 JitterMagic 套件也可簡單替換掉,以上為分享 Polly 重試機制搭配 jitter 策略的簡單實作,若有問題歡迎一起討論,謝謝 :)

0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com