بهینهسازی کارایی رندرینگ سمت سرور در Blazor 11x با مولفه CacheView
نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۵/۲۶ ۱۱:۵۰
آدرس: www.dntips.ir
چکیده: رندرینگ سمت سرور ثابت (Static Server-Side Rendering یا SSR) در چارچوب کاری Blazor به توسعهدهندگان اجازه میدهد تا صفحات وب را با سرعت بارگذاری اولیه بالا و بهینهسازی موتورهای جستجو (SEO) تولید کنند. با این حال، رندر مجدد زیردرختهای کامپوننتی سنگین در هر درخواست HTTP، میتواند فشار پردازشی (CPU Overhead) و نرخ تخصیص حافظه (Memory Allocation) را به شدت افزایش دهد. مایکروسافت در بهروزرسانیهای جدید اکوسیستم داتنت (از پیشنمایشهای NET 10 / 11.)، قابلیت جدیدی تحت عنوان کامپوننت CacheView معرفی کرده است. این کامپوننت با ذخیرهسازی خروجی HTML تولیدشده از بخشهای سنگین صفحه، در درخواستهای بعدی از نمونهسازی (Instantiation) و اجرای مجدد چرخه حیات کامپوننتها جلوگیری میکند. این مقاله به بررسی معماری CacheView، استراتژیهای انقضا، ابعاد تفکیک کش (Vary-By Dimensions)، یکپارچگی با لایه کش توزیعشده HybridCache و مکانیزمهای حفظ امنیت داده از طریق اتریبیوتهای رفتاری کش (CacheBehavior) میپردازد.
IMemoryCache یا IDistributedCache بودند؛ رویکردی که اگرچه فراخوانیهای پایگاه داده را حذف میکرد، اما هزینه رندرینگ و تولید HTML کامپوننت در سمت سرور همچنان پابرجا میماند. کامپوننت این خلاء را با کش کردن مستقیم خروجی رندر شده (Rendered HTML Fragment) پر میکند.CacheViewOnInitializedAsync یا OnParametersSetAsync) فراخوانی نمیگردند.@using Microsoft.AspNetCore.Components
<CacheView ExpiresAfter="TimeSpan.FromMinutes(10)"
VaryByRoute="productId"
VaryByQuery="page,pageSize"
VaryByCulture="true">
<ExpensiveProductSummary ProductId="productId" />
</CacheView>CacheView از مدلهای استاندارد انقضا پشتیبانی میکند:ExpiresAfter): تعیین طول عمر مشخص بر حسب بازه زمانی (مانند TimeSpan.FromMinutes(10)).ExpiresOn): تعیین زمان دقیق انقضا با DateTimeOffset.ExpiresSliding): تمدید اعتبار کش در صورت ارسال درخواستهای مکرر در بازه تعیینشده.VaryByRoute: تفکیک بر اساس پارامترهای مسیر URL (مثلاً شناسه رکورد یا اسلاگ).VaryByQuery: تفکیک بر اساس پارامترهای Query String (مانند فیلترها و شماره صفحه).VaryByCulture: تفکیک بر اساس Culture فعلی برنامه برای پشتیبانی از سیستمهای چندزبانه.VaryByUser: تفکیک بر اساس کاربر احراز هویت شده (ClaimsPrincipal).VaryByHeader / VaryByCookie: تفکیک بر اساس مقادیر هدر یا کوکیهای مشخص.VaryBy: پذیرش یک رشته سفارشی دلخواه برای سناریوهای خاص بیزینس.CacheKey: ایجاد تمایز میان چندین مرز CacheView تحت یک کامپوننت والد یکسان.نکته امنیتی و فنی: کش کردن به صورت خودکار برای متدهای غیر ازGET(مانندPOST)، در زمان تنظیمEnabled="false"، و در حین فرآیند رندر جریانی (Streaming SSR) متوقف میشود تا از ذخیرهسازی دادههای موقت یا ناقص جلوگیری گردد.
HybridCacheCacheView از یک مخزن حافظه رم درونبرنامهای (In-Memory) با سقف حجم مشخص (به طور پیشفرض 100 مگابایت قابل تنظیم از طریق RazorComponentsServiceOptions.CacheViewSizeLimit) استفاده میکند. در سامانههای توزیعشده و چندسروری (Load-Balanced Clusters)، ذخیرهسازی صرفاً در حافظه محلی منجر به عدم هماهنگی دادهها میشود. CacheView به طور بومی با انتزاع قدرتمند HybridCache هماهنگ است. با ثبت HybridCache در کانتینر تزریق وابستگی (DI)، کامپوننت CacheView به شکل خودکار به یک سیستم کش دو لایهای (Two-Tier) مجهز میشود؛ به طوری که لایه اول L1 (حافظه محلی درون پروسس) و لایه دوم L2 (ردیس، اسکیوال یا سایر پایگاههای داده توزیعشده) را بدون تغییر کد ویو پوشش میدهد.// Program.cs
builder.Services.AddHybridCache();
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();[CacheBehavior(CacheBehavior.Rerender)] (مکانیزم سوراخکاری / Hole-punching):CacheView با وضعیت Hit قرار داشته باشد، در هر درخواست مجدداً رندر میشود و خروجی جدید آن در ساختار کش تزریق میگردد.AntiforgeryToken (جهت حفظ امنیت توکنهای ضد جعل) و HeadOutlet (تغییر پویای متاتگهای سربرگ).[CacheBehavior(CacheBehavior.Throw)]:CacheView استفاده شود، سرور خطای سیستمی پرتاب میکند تا از انتشار اشتباه داده جلوگیری شود.[CacheCondition(CacheVaryBy.…)]:Throw است و مشخص میکند در چه صورتی کش کردن این کامپوننت مجاز است.| نام کامپوننت | انوتیشن (Annotation) | رفتار و شرایط لازم |
AntiforgeryToken / HeadOutlet | Rerender | همیشه در هر درخواست مجدداً رندر میشوند (بدون کش). |
AuthorizeView | Throw + CacheCondition(CacheVaryBy.User) | قرارگیری درون کش غیرمجاز است، مگر اینکه VaryByUser="true" باشد. |
QuickGrid | Throw + CacheCondition(CacheVaryBy.Query) | وابسته به پارامترهای صفحهبندی/مرتبسازی؛ نیازمند تعریف VaryByQuery. |
Virtualize | Throw | به طور مطلق درون CacheView پشتیبانی نمیشود. |
System.InvalidOperationException: Component 'QuickGrid`1[...]' cannot be used inside a CacheView because its output depends on per-request state ([CacheBehavior(CacheBehavior.Throw)], [CacheCondition(CacheVaryBy.Query)]) that cannot be safely cached and replayed. To fix this, configure the CacheView to vary by Query, or move the component outside the CacheView.
HybridCache و حفاظت پیشگیرانه در برابر نشت داده به کمک [CacheBehavior]، ابزاری مطمئن و با کارایی بالا در اختیار توسعهدهندگان ارشد داتنت برای ساخت وبسایتهای پرترافیک و بهینهسازی هزینههای زیرساخت ابری قرار میدهد.