Response Caching چیست؟
Response Caching یک مکانیزم ذخیره سازی پاسخ سرور توسط مرورگر یا سایر کلاینت ها است. Response Caching به درخواستهای آینده برای همان منابع کمک میکند. علاوه بر این، این کار سرور را از پردازش و ایجاد چندین بار پاسخ یکسان آزاد می کند.
ASP.NET Core از ویژگی ResponseCache برای تنظیم هدرهای response caching استفاده می کند. علاوه بر این، میتوانیم از میان افزار Response Caching برای کنترل رفتار ذخیرهسازی سمت سرور استفاده کنیم. هنگامی که هدرهای response caching را تنظیم میکنیم، کلاینتها و سایر پراکسیها میتوانند آنها را بخوانند تا نحوه response caching از سرور را تعیین کنند. طبق مشخصات کش پاسخ HTTP 1.1، مرورگرها، کلاینت ها و پراکسی ها باید با هدرهای ذخیره سازی مطابقت داشته باشند.
می توانید ویدیو بررسی و پیاده سازی Response Caching در ASP.NET Core 8 را در یوتیوب کدسل مشاهده کنید.
Response Caching مبتنی بر HTTP
در Asp.net core می توانیم بر اساس HTTP Cache Directive های مختلف، رفتار کش را کنترل کنیم.
Cache-Control فیلد هدر اولیه است که ما از آن برای مشخص کردن روش کش کردن پاسخ استفاده می کنیم. هنگامی که هدر cache-control در پاسخ وجود دارد، مرورگرها، کلاینت ها و سرورهای پراکسی باید هدرها را رعایت کرده و با آنها مطابقت داشته باشند.
Directive های رایج Cache-Control
Public: نشان می دهد که یک کش می تواند پاسخ را در سمت کلاینت یا در یک مکان مشترک ذخیره کند.
Private: نشان می دهد که فقط یک کش خصوصی در سمت کلاینت ممکن است پاسخ را ذخیره کند، اما یک حافظه کش مشترک وجود ندارد.
no-cache: مشخص می کند که کش نباید از یک پاسخ ذخیره شده برای هیچ درخواستی استفاده کند.
no-store: نشان می دهد که کش نباید پاسخ را ذخیره کند.
no-cache وno-store ممکن است شبیه به هم به نظر برسند و حتی رفتار مشابهی داشته باشند، اما در نحوه درک مرورگرها یا کلاینت ها تفاوتهایی وجود دارد.
به غیر از Cache-Control، چند هدر دیگر وجود دارد که می تواند رفتار کش را کنترل کند:
هدر pragma برای سازگاری با مشخصات HTTP 1.0 و دستورالعمل بدون کش است. اگر هدر cache-control را مشخص کنیم، هدر پراگما را نادیده می گیرد.
Vary - نشان می دهد که تنها در صورتی می تواند یک پاسخ کش شده را ارسال کند که تمام فیلدهایی که در هدر ارائه می کنیم دقیقاً با درخواست قبلی مطابقت داشته باشند. اگر هر یک از فیلدها تغییر کند، سرور یک پاسخ جدید ایجاد می کند.
مثال HTTP Cache Directive در Asp.net core
اکنون میخواهیم یک برنامه ASP.NET Core ایجاد کنیم و cache directive ها را در عمل ببینیم. بیایید یک پروژه ASP.NET Core Web API ایجاد کنیم و یک controller action method اضافه کنیم:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok($"Response was generated at {DateTime.Now}");
}
}
هر بار که این endpoint را اجرا می کنیم، می توانیم مشاهده کنیم که تاریخ و زمان واقعی اجرا را به پاسخ اضافه می کند. اکنون میخواهیم کش را به emdpoint اضافه کنیم.
نکته مهم: در حین تست کش، همیشه باید روی لینک های صفحه وب کلیک کنیم یا از Swagger برای اجرای API endpoint ها در مرورگر استفاده کنیم. در غیر این صورت، اگر سعی کنیم صفحه را رفرش کنیم یا دوباره URI را فراخوانی کنیم، مرورگر همیشه بدون توجه به تنظیمات response cache ، از سرور درخواست پاسخ جدیدی می کند.
ویژگی(Attribute) ResponseCache در Asp.net core
برای یک برنامه ASP.NET Core، ویژگی ResponseCache ویژگی هایی را برای تنظیم هدرهای response caching تعریف می کند. ما میتوانیم این ویژگی را در سطح Controller یا برای endpoint جداگانه اعمال کنیم.
بیایید ویژگی ResponseCache را به API endpoint اضافه کنیم:
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Any)]
public IActionResult Get()
{
return Ok($"Response was generated at {DateTime.Now}");
}
این ویژگی Duration هدر max-age را تولید میکند که از آن برای تنظیم مدت زمان کش برای 2 دقیقه (120 ثانیه) استفاده میکنیم. به طور مشابه، ویژگی Location مکان را در هدر cache-control تنظیم می کند. از آنجایی که ما مکان را به صورت Any تنظیم می کنیم، هم کلاینت و هم سرور می توانند پاسخ را در کش ذخیره کنند، که معادل دستور public هدر cache-control است.
بنابراین ، بیایید از API endpoint استفاده کنیم و این موارد را در هدرهای پاسخ ببنیم:
cache-control: public,max-age=120
علاوه بر این، هنگامی که چندین بار endpint را فراخوانی می کنیم، هر زمان که مرورگر از یک پاسخ کش شده استفاده می کند، در کد وضعیت نشان می دهد که پاسخ از disk cache گرفته شده است:
Status Code: 200 (from disk cache)
اکنون بیایید گزینه های مختلف برای پارامترهای ResponseCache را بررسی کنیم.
برای تغییر مکان کش به private، فقط باید مقدار ویژگی Location را به ResponseCacheLocation.Client تغییر دهیم:
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Client)]
این مقدار هدر cache-control را به private تغییر میدهد، به این معنی که فقط کلاینت میتواند پاسخ را کش کند:
cache-control: private,max-age=120
اکنون بیایید پارامتر Location را به Responsecachelocation.none بروز کنیم:
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.None)]
با این کار هدر cache-control و pragma روی no-cache تنظیم میشود، به این معنی که کلاینت نمیتواند از یک پاسخ کش شده بدون تأیید مجدد با سرور استفاده کند:
cache-control: no-cache,max-age=120
در این پیکربندی، میتوانیم بررسی کنیم که مرورگر از پاسخ کش شده استفاده نمیکند و سرور هر بار یک پاسخ جدید تولید میکند.
پراپرتی NoStore
اکنون بیایید پراپرتی NoStore در اتربیوت [ResponseCache] را تنظیم کنیم:
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Any, NoStore = true)]
این هدر پاسخ cache-control را روی no-store تنظیم می کند که نشان می دهد کلاینت نباید پاسخ را کش کند:
cache-control: no-store
توجه داشته باشید که این مقداری را که برای Location تنظیم کردهایم لغو میکند. در این مورد نیز، کلاینت پاسخ را کش نخواهد کرد.
حتی اگر مقادیر no-cache و no-store برای cache-control ممکن است نتایج یکسانی را در حین تست ارائه دهند، مرورگرها، کلاینت ها و پراکسی ها این هدرها را متفاوت تفسیر می کنند. در حالی که no-store نشان میدهد که کلاینتها یا پراکسیها نباید پاسخ یا بخشی از آن را در جایی ذخیره کنند، no-cache فقط به این معنی است که کلاینت نباید از پاسخ کش شده بدون تأیید مجدد با سرور استفاده کند.
پراپرتی VaryByHeader
برای تنظیم هدر vary، میتوانیم از ویژگی VaryByHeader در اتربیوت ResponseCache استفاده کنیم:
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Any, VaryByHeader = "User-Agent")]
در اینجا مقدار خاصیت VaryByHeader را روی User-Agent قرار می دهیم که تا زمانی که درخواست از همان دستگاه کلاینت ارسال شود، از پاسخ کش شده استفاده می کند. هنگامی که دستگاه کلاینت تغییر می کند، مقدار User-Agent متفاوت خواهد بود و پاسخ جدیدی از سرور دریافت می کند.
پراپرتی VaryByQueryKeys
با استفاده از ویژگی VaryByQueryKeys در اتربیوت ResponseCache، میتوانیم کاری کنیم که سرور در هنگام تغییر پارامترهای رشته کوئری مشخص شده، پاسخ جدیدی ارسال کند. البته، با تعیین مقدار "*"، میتوانیم در صورت تغییر هر یک از پارامترهای رشته کوئری، پاسخ جدیدی تولید کنیم.
[HttpGet]
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new string[] { "id" })]
public IActionResult Get(int id)
{
return Ok($"Response was generated for Id:{id} at {DateTime.Now}");
}
به یاد داشته باشید که برای تنظیم ویژگی VaryByQueryKeys باید میان افزار Response Caching را فعال کنیم. در غیر این صورت، کد یک runtime exception ایجاد می کند.
میانافزار Response Caching
میانافزار Response Caching در برنامه ASP.NET Core تعیین میکند که چه زمانی میتوان یک پاسخ را در کش ذخیره کرد و پاسخ را از حافظه کش ارائه میکند.
برای فعال کردن Response Caching Middleware، فقط باید چند خط کد را در کلاس Program اضافه کنیم:
builder.Services.AddControllers();
builder.Services.AddResponseCaching();
...
var app = builder.Build();
...
app.MapControllers();
app.UseResponseCaching();
app.Run();
ابتدا باید سرویس ()AddResponseCaching را به کانتینر پروژه اضافه کنیم و سپس می توانیم برنامه را برای استفاده از میان افزار با متد UseResponseCaching () پیکربندی کنیم.
اکنون میانافزار Response Caching را فعال کردهایم و ویژگی VaryByQueryKeys باید کار کند.
بیایید برنامه را اجرا کنیم و به /values?id=1 برویم:
Response was generated for Id:1 at 23-05-2023 12:07:22
می بینیم که تا زمانی که رشته query یکسان باشد، یک پاسخ کش شده دریافت می کنیم، اما زمانی که رشته query را تغییر دهیم، سرور پاسخ جدیدی ارسال می کند.
بیایید رشته query را به /values?id=2 تغییر دهیم:
Response was generated for Id:2 at 23-05-2023 12:07:32
توجه داشته باشید که هیچ هدر HTTP متناظری برای ویژگی VaryByQueryKeys وجود ندارد. این ویژگی یک ویژگی HTTP است که توسط Response Caching Middleware مدیریت می شود.
Cache Profile ها در asp.net core
به جای کپی کردن تنظیمات response cache در کنترلر ها یا اکشن ها ، می توانیم پروفایل های کش را پیکربندی کرده و از آنها استفاده مجدد کنیم. هنگامی که یک نمایه کش را تنظیم می کنیم، برنامه می تواند از مقادیر آن به عنوان پیش فرض برای ویژگی ResponseCache استفاده کند. البته، میتوانیم پیشفرضها را با مشخص کردن پراپرتی ها در اتربیوت [ResponseCache] لغو کنیم.
ما می توانیم یک نمایه کش در کلاس Program تعریف کنیم:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.CacheProfiles.Add("Cache2Mins",
new CacheProfile()
{
Duration = 120,
Location = ResponseCacheLocation.Any
});
});
...
در اینجا یک نمایه کش جدید به نام Cache2Mins با مدت زمان 2 دقیقه و Location به عنوان public تعریف می کنیم.
اکنون می توانیم این نمایه کش را روی هر کنترلر یا action اعمال کنیم:
[HttpGet]
[ResponseCache(CacheProfileName = "Cache2Mins")]
public IActionResult Get()
{
return Ok($"Response was generated at {DateTime.Now}");
}
با این کار تنظیمات cache-control تعریف شده برای پاسخ اعمال می شود:
cache-control: public,max-age=120
به جای هارد کد کردن تنظیمات کش در کلاس Program، میتوانیم چندین نمایه کش را در فایل appsettings برنامه تعریف کنیم و تنظیمات response cache را قابل تنظیم کنیم:
{
"Logging": {
...
},
"CacheProfiles": {
"Cache2Mins": {
"Duration": 120,
"Location": "Any"
}
},
"AllowedHosts": "*"
}
سپس، میتوانیم پروفایلهای کش در کلاس Program را با استفاده از کلاس ConfigurationManager بخوانیم:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
var cacheProfiles = builder.Configuration
.GetSection("CacheProfiles")
.GetChildren();
foreach (var cacheProfile in cacheProfiles)
{
options.CacheProfiles
.Add(cacheProfile.Key,
cacheProfile.Get<CacheProfile>());
}
});
این روش بسیار بهتری برای تعریف نمایه های کش است، به خصوص زمانی که نیاز به تعریف چندین نمایه کش برای برنامه خود داشته باشیم.
نتیجه گیری
در این مقاله به موضوع response caching و نحوه استفاده از آن در asp.net core پرداختیم. علاوه بر این، ما یاد گرفتهایم که چگونه رفتار response caching را با تنظیم cache directive ها و استفاده از response caching middleware کنترل کنیم. در نهایت، نحوه تعریف نمایه کش و استفاده مجدد از آن در برنامه را یاد گرفتیم.
برای ثبت نظر باید در سایت ثبت نام یا ورود نمایید