تاب آوری و انعطاف پذیری در ASP.NET Core با Polly: ساخت برنامههای مقاوم در برابر خطا
تاب آوری به توانایی یک سیستم برای حفظ عملکرد و قابلیت استفاده در مواجهه با اختلالات و خطاها اشاره دارد. انعطاف پذیری نیز به توانایی سیستم برای بازیابی از این خطاها و بازگشت به حالت عادی اشاره میکند. در چارچوب ASP.NET Core، دستیابی به این ویژگیها نیازمند استفاده از ابزارها و الگوهای مناسب است. یکی از قدرتمندترین و محبوبترین کتابخانهها در این زمینه، Polly نام دارد.
Polly یک کتابخانه .NET جامع برای مدیریت خطاها و پیادهسازی استراتژیهای تاب آوری مانند تلاش مجدد (Retry)، قطع کننده مدار (Circuit Breaker)، زمان انتظار (Timeout)، و سیاستهای بازگشتی (Fallback) است. این کتابخانه با ارائه یک API روان و قابل فهم، به توسعهدهندگان کمک میکند تا به سادگی سیاستهای مختلفی را برای مقابله با خطاهای گذرا در برنامههای ASP.NET Core خود تعریف و اعمال کنند.
درک خطاهای گذرا
قبل از پرداختن به نحوه استفاده از Polly، مهم است که درک کنیم منظور از خطاهای گذرا چیست. این نوع خطاها معمولاً موقتی هستند و ممکن است به دلایل مختلفی رخ دهند، از جمله:
- مشکلات شبکه: قطعیهای موقت شبکه، تاخیر در پاسخگویی، یا از دست رفتن بستهها.
- بار زیاد بر روی سرویس: زمانی که یک سرویس خارجی تحت فشار زیاد قرار میگیرد و ممکن است به طور موقت پاسخگو نباشد.
- مشکلات موقت در زیرساخت: مشکلات سختافزاری یا نرمافزاری موقت در سرورها یا سرویسهای ابری.
- مسائل مربوط به پایگاه داده: مشکلات اتصال موقت، قفل شدن منابع، یا کندی در پاسخگویی.
این خطاها معمولاً با یک تلاش مجدد ساده پس از یک تاخیر کوتاه قابل حل هستند. با این حال، تلاشهای مکرر بدون هیچگونه استراتژی میتواند منجر به بار اضافی بر روی سیستمهای درگیر و حتی ایجاد مشکلات بزرگتر شود.
معرفی Polly: ناجی برنامههای ASP.NET Core
Polly با ارائه مجموعهای از سیاستهای از پیش تعریف شده، به توسعهدهندگان کمک میکند تا به شیوهای هوشمندانه و کارآمد با خطاهای گذرا مقابله کنند. این سیاستها به صورت زنجیرهای قابل ترکیب هستند و میتوانند برای محافظت از تعاملات مختلف در برنامه، از جمله تماس با سرویسهای HTTP، دسترسی به پایگاه داده، و تعامل با سایر منابع خارجی، مورد استفاده قرار گیرند.
برخی از مهمترین سیاستهای ارائه شده توسط Polly عبارتند از:
1. سیاست تلاش مجدد (Retry Policy)
این سیاست به برنامه اجازه میدهد تا در صورت بروز خطا، عملیات را برای تعداد مشخصی بار و با فواصل زمانی مشخص تکرار کند. این امر برای مقابله با خطاهای گذرا ناشی از مشکلات شبکه یا بار زیاد بر روی سرویس بسیار مفید است.
نحوه استفاده:
var retryPolicy = Policy
.Handle() // مشخص کردن نوع خطایی که باید برای آن تلاش مجدد انجام شود
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // 3 بار تلاش مجدد با تاخیر نمایی
در این مثال، سیاست تلاش مجدد برای خطاهای HttpRequestException
تعریف شده است. این سیاست سعی میکند عملیات را 3 بار تکرار کند. تاخیر بین هر تلاش به صورت نمایی افزایش مییابد (2 ثانیه، 4 ثانیه، 8 ثانیه).
2. سیاست قطع کننده مدار (Circuit Breaker Policy)
این سیاست از ارسال درخواستهای مکرر به یک سرویس که به طور مداوم با خطا مواجه میشود، جلوگیری میکند. هنگامی که تعداد مشخصی خطا در یک بازه زمانی معین رخ میدهد، مدار "باز" میشود و درخواستهای جدید بلافاصله با یک خطا مواجه میشوند. پس از یک دوره زمانی مشخص (نیمه باز)، یک درخواست آزمایشی ارسال میشود. اگر موفقیتآمیز باشد، مدار "بسته" میشود و روال عادی از سر گرفته میشود. در غیر این صورت، مدار همچنان "باز" میماند.
نحوه استفاده:
var circuitBreakerPolicy = Policy
.Handle()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); // اگر 5 خطا در 30 ثانیه رخ دهد، مدار باز میشود
این سیاست اگر 5 خطای HttpRequestException در بازه زمانی 30 ثانیه رخ دهد، مدار را باز میکند.
3. سیاست زمان انتظار (Timeout Policy)
این سیاست برای جلوگیری از مسدود شدن بینهایت برنامه در صورت عدم پاسخگویی یک سرویس خارجی استفاده میشود. اگر یک عملیات در بازه زمانی مشخص شده به پایان نرسد، یک استثنا رخ میدهد.
نحوه استفاده:
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(10)); // حداکثر 10 ثانیه برای انجام عملیات زمان در نظر گرفته میشود
این سیاست تعیین میکند که هر عملیاتی که تحت پوشش آن قرار میگیرد، باید ظرف 10 ثانیه به پایان برسد. در غیر این صورت، یک استثنای TimeoutRejectedException پرتاب میشود.
4. سیاست انزوای انبوه (Bulkhead Isolation Policy)
این سیاست برای محدود کردن تعداد درخواستهای همزمان به یک منبع خاص استفاده میشود. این کار به جلوگیری از فرسایش منابع و تضمین پایداری سایر بخشهای سیستم کمک میکند. به عنوان مثال، میتوان از این سیاست برای محدود کردن تعداد درخواستهای همزمان به یک سرویس خارجی با ظرفیت محدود استفاده کرد.
نحوه استفاده (مثال مفهومی):
var bulkheadPolicy = Policy
.BulkheadAsync(5, 2); // حداکثر 5 درخواست همزمان و 2 درخواست در صف انتظار
این سیاست اجازه میدهد تا حداکثر 5 درخواست به طور همزمان اجرا شوند و 2 درخواست دیگر در صف منتظر بمانند. درخواستهای بعدی بلافاصله رد میشوند.
5. سیاست بازگشتی (Fallback Policy)
این سیاست به برنامه اجازه میدهد تا در صورت بروز خطا و عدم موفقیت سایر سیاستها، یک رفتار جایگزین را ارائه دهد. این میتواند شامل بازگرداندن یک مقدار پیش فرض، نمایش یک پیام خطا دوستانه، یا استفاده از یک منبع داده محلی باشد.
نحوه استفاده:
var fallbackPolicy = Policy
.Handle()
.FallbackAsync(async ct => new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("سرویس موقتا در دسترس نیست. لطفا بعدا تلاش کنید.")
});
این سیاست در صورت بروز خطای HttpRequestException، یک پاسخ HTTP با کد 500 و یک پیام خطا را برمیگرداند.
یکپارچهسازی Polly با ASP.NET Core
Polly به راحتی با برنامههای ASP.NET Core یکپارچه میشود. رایجترین روش استفاده از آن، از طریق HttpClientFactory
است. با استفاده از متدهای توسعه ارائه شده توسط Polly، میتوان سیاستهای مختلف را به صورت پیکربندی شده به HttpClient
اضافه کرد.
مراحل یکپارچهسازی:
1. نصب بسته NuGet: ابتدا بسته NuGet Microsoft.Extensions.Http.Polly را به پروژه ASP.NET Core خود اضافه کنید.
Install-Package Microsoft.Extensions.Http.Polly
2. پیکربندی سیاستها در Program.cs (یا Startup.cs در نسخههای قدیمیتر):
// در Program.cs
builder.Services.AddHttpClient("MyApiClient")
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
// یا در Startup.cs (ConfigureServices متد)
services.AddHttpClient("MyApiClient")
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
3. در این مثال، یک HttpClient با نام MyApiClient پیکربندی شده است که از دو سیاست استفاده میکند: یک سیاست تلاش مجدد و یک سیاست قطع کننده مدار. متد AddTransientHttpErrorPolicy برای اعمال سیاستها در صورت بروز خطاهای HTTP گذرا (مانند خطاهای 5xx یا خطاهای مربوط به شبکه) استفاده میشود.
-
استفاده از HttpClient در کد:
public class MyService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger _logger;
public MyService(IHttpClientFactory httpClientFactory, ILogger logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}
public async Task<string> GetDataFromExternalServiceAsync()
{
var client = _httpClientFactory.CreateClient("MyApiClient");
try
{
var response = await client.GetAsync("https://example.com/api/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
_logger.LogError($"خطا در هنگام فراخوانی سرویس خارجی: {ex.Message}");
throw; // یا میتوان از یک سیاست بازگشتی در اینجا استفاده کرد
}
}
}
در این کد، یک نمونه از HttpClient با نام MyApiClient از IHttpClientFactory ایجاد شده و برای ارسال درخواست به یک سرویس خارجی استفاده میشود. سیاستهای پیکربندی شده به طور خودکار توسط Polly اعمال میشوند.
ترکیب سیاستها با PolicyWrap
Polly به شما امکان میدهد تا چندین سیاست را با استفاده از PolicyWrap ترکیب کنید. این امر به شما اجازه میدهد تا استراتژیهای پیچیدهتری را برای مدیریت خطاها ایجاد کنید. به عنوان مثال، میتوانید یک سیاست تلاش مجدد را با یک سیاست قطع کننده مدار و یک سیاست زمان انتظار ترکیب کنید.
var retryPolicy = Policy
.Handle()
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
var circuitBreakerPolicy = Policy
.Handle()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(10));
var wrappedPolicy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy, timeoutPolicy);
// استفاده از wrappedPolicy برای اجرای یک عمل
try
{
await wrappedPolicy.ExecuteAsync(async () => await client.GetAsync("https://example.com/api/data"));
}
catch (Exception ex)
{
// مدیریت خطا
}
در این مثال، ابتدا سه سیاست جداگانه (تلاش مجدد، قطع کننده مدار، و زمان انتظار) تعریف شدهاند. سپس با استفاده از Policy.WrapAsync، این سیاستها به ترتیب مشخص با یکدیگر ترکیب شدهاند. هنگام اجرای عمل با استفاده از wrappedPolicy.ExecuteAsync، سیاستها به ترتیب اعمال میشوند.
مزایای استفاده از Polly در ASP.NET Core
استفاده از Polly در برنامههای ASP.NET Core مزایای متعددی دارد، از جمله:
- افزایش تاب آوری: Polly به برنامهها کمک میکند تا در مواجهه با خطاهای گذرا به طور موثرتری عمل کنند و از خرابیهای احتمالی جلوگیری کنند.
- بهبود تجربه کاربری: با کاهش احتمال بروز خطا و ارائه رفتارهای جایگزین در صورت بروز مشکل، تجربه کاربری بهبود مییابد.
- کاهش بار بر روی سیستمهای پایین دستی: سیاستهایی مانند قطع کننده مدار از ارسال درخواستهای غیرضروری به سرویسهای مشکلدار جلوگیری میکنند و بار را بر روی آنها کاهش میدهند.
- کد تمیزتر و خواناتر: Polly با ارائه یک API روان و قابل فهم، پیادهسازی استراتژیهای مدیریت خطا را آسانتر میکند و کد را خواناتر و قابل نگهداریتر میسازد.
- قابلیت پیکربندی بالا: Polly امکان پیکربندی دقیق سیاستها را بر اساس نیازهای خاص برنامه فراهم میکند.
ملاحظات و بهترین شیوهها
در هنگام استفاده از Polly، توجه به نکات زیر ضروری است:
- انتخاب سیاستهای مناسب: نوع سیاستها و تنظیمات آنها باید بر اساس نوع خطاها و ویژگیهای سیستمهای درگیر انتخاب شوند.
- آزمایش دقیق: استراتژیهای تاب آوری باید به طور کامل آزمایش شوند تا از عملکرد صحیح آنها در شرایط مختلف اطمینان حاصل شود.
- مانیتورینگ و لاگینگ: نظارت بر عملکرد سیاستهای Polly و ثبت رویدادهای مربوط به خطاها میتواند به شناسایی و رفع مشکلات احتمالی کمک کند.
- اجتناب از تلاش مجدد بینهایت: تنظیم تعداد مناسب برای تلاشهای مجدد و استفاده از استراتژیهای تاخیر مناسب برای جلوگیری از بار زیاد بر روی سیستمهای درگیر ضروری است.
- در نظر گرفتن اثرات جانبی: هنگام استفاده از سیاست تلاش مجدد، به اثرات جانبی احتمالی عملیات توجه کنید. برخی از عملیات نباید به طور خودکار تکرار شوند (مانند تراکنشهای مالی).
نتیجهگیری
تاب آوری و انعطاف پذیری از ویژگیهای حیاتی برای برنامههای ASP.NET Core هستند که در محیطهای پیچیده و توزیع شده امروزی اجرا میشوند. کتابخانه Polly با ارائه مجموعهای قدرتمند از سیاستهای مدیریت خطا، به توسعهدهندگان کمک میکند تا به سادگی و به شیوهای موثر این ویژگیها را در برنامههای خود پیادهسازی کنند. با استفاده از سیاستهای تلاش مجدد، قطع کننده مدار، زمان انتظار، انزوای انبوه، و بازگشتی، میتوان برنامههایی ساخت که در برابر خطاهای گذرا مقاوم بوده و تجربه کاربری بهتری را ارائه میدهند. یکپارچهسازی آسان Polly با ASP.NET Core از طریق HttpClientFactory و امکان ترکیب سیاستها با PolicyWrap، این کتابخانه را به یک ابزار ارزشمند برای هر توسعهدهنده ASP.NET Core تبدیل کرده است که به دنبال ساخت برنامههای کاربردی قابل اعتماد و مقاوم در برابر خطا است. با در نظر گرفتن بهترین شیوهها و انجام آزمایشهای دقیق، میتوان از تمام پتانسیل Polly برای ساخت برنامههای کاربردی پایدار و کارآمد بهره برد.
0 نظر
هنوز نظری برای این مقاله ثبت نشده است.