Polly در سی شارپ ؛ در این مقاله میخواهیم راجب تلاش مجدد درخواستهای ناموفق با Polly در سی شارپ صحبت کنیم. تا پایان این مقاله همراه ما باشید.
بیایید نگاهی به چگونگی پیادهسازی الگوی تلاش مجدد در سی شارپ با استفاده از Polly، برای مواقعی که نیاز داریم بعد از تعداد تلاش مجدد بتوانیم خروجی مورد نیاز از برنامه را داشته باشیم. در ادامه به صورت قدم به قدم موارد را پیش میرویم.
سناریو
برای نشان دادن سناریو، برنامهای ساده ایجاد کردیم که سعی خواهد کرد محتوای وبسایت ما را دانلود کرده و از اطلاعات و یا پیغام خطا، بسته به اینکه درخواست موفقیت آمیز بوده یا خیر، گزارش تهیه کند:
class Program { static async Task Main(string[] args) { var logger = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.ColoredConsole() .CreateLogger(); var httpClient = new HttpClient(); var response = await httpClient.GetAsync("https://www.jerriepelser.com"); if (response.IsSuccessStatusCode) logger.Information("Response was successful."); else logger.Error($"Response failed. Status code {response.StatusCode}"); } }
برای شبیهسازی خطاهای متفاوت شبکه، AutoResponder مربوط به Fiddler را جهت بازگردانی یک کد وضعیت ۴۰۴ در ۵۰% مواقع برای درخواستهایی به دامنهی jerriepelser.com پیکربندی کردهام:
این بدین معناست که گاها زمانی که کد فوق را اجرا کنیم، یک پیغام موفق دریافت خواهیم کرد:
اما در دیگر مواقع ممکن است پیغام خطا را دریافت کنیم:
Polly to the rescue
حال، بیایید آن را با استفاده از Polly انعطافپذیرتر کنیم. ابتدا، Polly NuGet Package را نصب کنید.
dotnet add package Polly
جهت پیادهسازی سیاست تلاش مجدد با Polly، به آن خواهیم گفت که یک نتیجهی HttpResponseMeddage را که در آن خاصیت IsSuccessStatusCode را برای مشخص کردن این که آیا درخواست موفق بوده یا خیر بررسی خواهیم کرد، مدیریت کند.
اگر IsSuccessStatusCode true باشد، درخواست موفق بوده، در غیر اینصورت، موفق نبوده است.
فراخوانی متد WaitAndRetryAsync به Polly دستور میدهد تا سه بار تلاش مجدد کند، و بین تلاشهای مجدد ۲ ثانیه صبر کند.
همچنین یک پارامتر onRetry مشخص میکنیم که یک delegate است که اطلاعات وضعیت را، از جمله این که کد وضعیتی که بازگردانده شده چه بوده، چه مدت برای تلاش صبر میکنیم و این کدام سعی برای تلاش مجدد خواهد بود، به سادگی گزارشگیری خواهد کرد.
درنهایت، ExecuteAsync را با یک پارامتر action فراخوانی میکنیم که یک لاندا میباشد که HttpResponseMessage را به سادگی از فراخوان ما به HttpClient.GetAsync باز میگرداند که Polly آن را به مدیریت کنندهای که پیشتر تعیین کردیم، به همراه فراخوانی به HandleResult ارسال خواهد کرد، تا مشخص شود که آیا درخواست موفق بوده یا خیر.
static async Task Main(string[] args) { var logger = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.ColoredConsole() .CreateLogger(); var httpClient = new HttpClient(); var response = await Policy .HandleResult<HttpResponseMessage>(message => !message.IsSuccessStatusCode) .WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(2), (result, timeSpan, retryCount, context) => { logger.Warning($"Request failed with {result.Result.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}"); }) .ExecuteAsync(() => httpClient.GetAsync("https://www.jerriepelser.com")); if (response.IsSuccessStatusCode) logger.Information("Response was successful."); else logger.Error($"Response failed. Status code {response.StatusCode}"); }
با درست کردن این مورد، برنامه را چندبار اجرا کردیم تا به نمونهای برسیم که در آن برنامه باید سه تلاش مجدد را انجام میداد.
همانطور که میتوانید مشاهده کنید، Polly سه بار تلاش مجدد انجام داد، بین هر بار دو ثانیه پیش از تلاش مجدد برای درخواست صبر کرد و در نهایت در سعی برای سومین تلاش مجدد موفق شد:
Exponential back-off
در نمونهی فوق، به Polly گفتیم که سه مرتبه تلاش مجدد انجام دهد، و بین هر بار سعی برای تلاش مجدد ۲ ثانیه صبر کند، اما یک نفر میتواند به جای آن یک استراتژی عقبگرد نمایی را پیادهسازی کند.
برای مثال، میتوانیم به Polly بگوییم یک ثانیه پیش از اولین تلاش مجدد، سپس دو ثانیه پیش از دومین تلاش مجدد و درنهایت پنج ثانیه پیش از آخرین تلاش مجدد صبر کند.
بدین منظور، یک IEnumerable<TimeSpan> به متد WaitAndRetryAsync مشخصکنندهی توالی مدت زمان بین سعی در تلاشهای مجدد ارسال میکنیم:
var response = await Policy .HandleResult<HttpResponseMessage>(message => !message.IsSuccessStatusCode) .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5) }, (result, timeSpan, retryCount, context) => { logger.Warning($"Request failed with {result.Result.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}"); }) .ExecuteAsync(() => httpClient.GetAsync("https://www.jerriepelser.com"));
اکنون هنگامی که به سناریویی میرسیم که در آن برنامه باید سه بار تلاش مجدد انجام دهد، میتوانید مشاهده کنید که سیاست تلاش مجدد به همراه عقبگرد نمایی به درستی اجرا شدهاست:
نتیجهگیری
در این پست، نحوهی استفاده از سیاست Retry در Polly را برای بازیابی خودکار از خطاهایی مانند خطاهای متناوب شبکه در برنامهی خود نشان داده ایم.
دیدگاهها