گذار به تابآوری بومی: بررسی راهبرد مایکروسافت با ارائه بسته Microsoft.Extensions.Resilience در داتنت نوین
نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۷/۱۱ ۱۱:۰۵
آدرس: www.dntips.ir
چکیده: در سیستمهای توزیعشده و معماریهای مبتنی بر ریزسرویسها (Microservices)، بروز خطاهای گذرا (Transient Faults) امری اجتنابناپذیر است. سالها کتابخانه شناختهشده Polly مرجع اصلی پیادهسازی الگوهای تابآوری نظیر تلاش مجدد (Retry)، قطعکننده مدار (Circuit Breaker) و محدودکننده نرخ (Rate Limiter) در جامعه داتنت بود. با این حال، نیاز مبرم به کارایی بالاتر، همگرایی با استانداردهای رصدپذیری (Observability)، کاهش سربار تخصیص حافظه و یکپارچگی عمیقتر با هسته فریمورک، مایکروسافت را بر آن داشت تا با بازطراحی ساختاری Polly (نسخه ۸ به بعد) بسته رسمی Microsoft.Extensions.Resilience را ارائه کند. این مقاله به بررسی فنی معماری این بسته نوین، مزایای آن از منظر کارایی، رصدپذیری استاندارد، و جایگزینی انتزاعات قدیمی با خطلولههای تابآوری (Resilience Pipelines) میپردازد.Microsoft.Extensions.Http.Polly انجام میشد. این رویکرد، با وجود پاسخگویی به نیازهای اولیه، با چندین محدودیت فنی اساسی همراه بود:Microsoft.Extensions.Resilience را به عنوان یک راهکار بومی/توکار (In-box) با عملکرد بالا معرفی نمود.Request ──► [ Rate Limiter ] ──► [ Circuit Breaker ] ──► [ Retry ] ──► [ Timeout ] ──► Core Execution
ValueTask، خطلولهها را برای سناریوهای فوق پرسرعت (High-Throughput) بهینهسازی کرده است.HttpClient متمرکز بودند، خطلولهها از نوع اجرا مستقلاند؛ میتوان آنها را برای پایگاهداده، کش، فراخوانیهای gRPC یا محاسبات درونبرنامهای به کار بست.// رویکرد سنتی و وابسته به پکیجهای قدیمی
services.AddHttpClient("LegacyClient")
.AddTransientHttpErrorPolicy(policy =>
policy.WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(2)))
.AddTransientHttpErrorPolicy(policy =>
policy.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));Microsoft.Extensions.Resilience)// فعالسازی بسته جامع تابآوری روی HttpClient
builder.Services.AddHttpClient("ModernClient", client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddStandardResilienceHandler(options =>
{
// سفارشیسازی تنظیمات در صورت نیاز
options.Retry.MaxRetryAttempts = 3;
options.Retry.Delay = TimeSpan.FromSeconds(1);
options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(5);
options.CircuitBreaker.SamplingDuration = TimeSpan.FromSeconds(10);
});// تعریف و ثبت خطلوله عمومی در DI
builder.Services.AddResiliencePipeline("database-pipeline", pipelineBuilder =>
{
pipelineBuilder
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 2,
Delay = TimeSpan.FromMilliseconds(500)
})
.AddTimeout(TimeSpan.FromSeconds(3));
});
// استفاده در یک سرویس کاری
public class ProductService(ResiliencePipelineProvider<string> pipelineProvider)
{
public async ValueTask<Product?> GetProductAsync(int id, CancellationToken ct)
{
var pipeline = pipelineProvider.GetPipeline("database-pipeline");
return await pipeline.ExecuteAsync(async state =>
{
return await QueryDatabaseAsync(id, state);
}, ct);
}
private static ValueTask<Product?> QueryDatabaseAsync(int id, CancellationToken ct)
{
// شبیهسازی فراخوانی پایگاه داده
return ValueTask.FromResult<Product?>(new Product(id, "لپتاپ"));
}
}
public record Product(int Id, string Name);Microsoft.Extensions.Resilience، انتشار پیشفرض و استاندارد متریکهای عملیاتی بر پایه کتابخانه System.Diagnostics.Metrics است.appsettings.json) را دارند و بدون کامپایل مجدد، از طریق پیکربندی مجدد و Hot Reload قابل بهروزرسانی هستند.Microsoft.Extensions.Resilience، نمونهای برجسته از بلوغ اکوسیستم مدرن داتنت است. مایکروسافت با رفع کاستیهای معماری سنتی و تکیه بر بازطراحی خطلولههای کممصرف، الگوهای تابآوری را از یک «پکیج اختیاری شخص ثالث» به یک «ستون بنیادین فریمورک» ارتقا داده است.Polly.Core)Polly.Core: تمام الگوهای قدیمی (v7) کنار گذاشته شدند و یک هسته جدید بر مبنای ResiliencePipeline با تخصیص حافظه نزدیک به صفر (Zero-Allocation) درون مخزن گیتهاب رسمی Polly بازنویسی شد. مهندسان تیم .NET مایکروسافت مستقیماً در نوشتن کد و بهینهسازی این هسته مشارکت داشتند.Microsoft.Extensions.Resilience: بستهای رسمی از سوی مایکروسافت است که لایهای از انتزاعات بالاتر را روی Polly.Core میکشد. کار این پکیج تزریق وابستگی، ساخت زنجیرههای پیشفرض استاندارد (AddStandardResilienceHandler)، اتصال به سیستم لاگینگ داتنت، پیوند با IOptions و انتشار متریکهای تلهمتری است.پروژه شما
└── Microsoft.Extensions.Resilience (تحت نظارت و لایسنس مایکروسافت)
└── Microsoft.Extensions.Http.Resilience
└── Polly.Core (نسخه 8+)Microsoft.Extensions.*، این کتابخانه وارد چرخه حیات رسمی فریمورک داتنت شده است. اگر در شرکتی کار میکنید که لایسنسهای پشتیبانی مایکروسافت را دارد، باگها و مشکلات عملکردی این پکیج توسط تیم داتنت بررسی و پشتیبانی میشود.AddStandardResilienceHandler() کامپوننتهای تابآوری را به عنوان بخشی استاندارد و یکدست از اکوسیستم برنامه به شما تحویل میدهند، هرچند که در موتورخانه، این Polly v8 است که بار اجرا را به دوش میکشد.