對 Response 回傳結果適時的使用快取機制,可以有助於效能提升,避免重複的運算浪費。
本篇將介紹 ASP.NET Core 如何設定 Response 的 Client 端暫存及Server 端快取。
同步發佈至個人部落格:
John Wu's Blog - [鐵人賽 Day28] ASP.NET Core 2 系列 - Response 快取
ASP.NET Core 對於網頁的 Response 快取有分兩種:
ASP.NET Core 可以透過 [ResponseCache]
設定 Response 的暫存方式。並套用到要使用 Response 快取的 Controller 或 Action。
透過 HTTP Header 的 Cache-Control
告知瀏覽器,把頁面存在瀏覽器暫存區。如下圖:
Client 端暫存只要套用 [ResponseCache]
即可,不需要多註冊額外的服務,如下:
Controllers\HomeController.cs
public class HomeController : Controller
{
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client)]
public IActionResult Index()
{
return View();
}
}
[ResponseCache]
可以設定的參數如下:
Duration
Location
ResponseCacheLocation.Any
Cache-Control: public
。ResponseCacheLocation.Client
Cache-Control: private
。ResponseCacheLocation.None
Cache-Control: no-cache
。NoStore
Cache-Control: no-store
。VaryByHeader
VaryByHeader="Cookie"
。VaryByQueryKeys
VaryByQueryKeys = new string[] { "q" }
。http://localhost:5000/?q=123
及 http://localhost:5000/?q=456
雖然是連上同一個 URL,但因為設定的 URL Query String 的 q
不同,所以 Response 暫存的內容也會有所不同。CacheProfileName
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.CacheProfiles.Add("Default",
new CacheProfile()
{
Duration = 60,
Location = ResponseCacheLocation.Client
});
});
}
// Controllers\HomeController.cs
public class HomeController : Controller
{
[ResponseCache(CacheProfileName = "Default")]
public IActionResult Index()
{
return View();
}
}
Server 端 Response 快取需要
Microsoft.AspNetCore.ResponseCaching
套件。
ASP.NET Core 2.0 以上版本,預設是參考Microsoft.AspNetCore.All
,已經包含Microsoft.AspNetCore.ResponseCaching
,所以不用再安裝。
Server 端 Response 快取功能是在 ASP.NET Core 1.1 之後的版本才有,如果是 ASP.NET Core 2.0 以前版本,可以透過 .NET Core CLI 在專案資料夾執行安裝指令:
dotnet add package Microsoft.AspNetCore.ResponseCaching
Server 端 Response 快取適合用在常被呼叫的頁面或 API,且資料是 可共用的資料 ,也就是所有網頁使用者看到的資料都一樣。當請求相同頁面時,會把上次的處理結果從 Server 的快取回傳給 Client,省去後續一連串的行為。如下圖:
如果要搭配 Server 端 Response 快取,除了套用 [ResponseCache]
外,還需要在 DI 容器注入 ResponseCaching 服務及註冊 ResponseCaching 的 Middleware,如下:
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace MyWebsite
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCaching(options =>
{
options.UseCaseSensitivePaths = false;
options.MaximumBodySize = 1024;
options.SizeLimit = 100 * 1024 * 1024;
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseResponseCaching();
app.UseMvcWithDefaultRoute();
}
}
}
Server 快取可以設定的參數如下:
UseCaseSensitivePaths
MaximumBodySize
SizeLimit
建立一個簡單的範例:
Controllers\HomeController.cs
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[ResponseCache(Duration = 360)]
public IActionResult Index()
{
var request = HttpContext.Request;
_logger.LogDebug($"URL: {request.Host}{request.Path}{request.QueryString}");
return View(model: DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
}
Views\Home\Index.cshtml
@model string
<p>Server Time: @Model</p>
<a href="?q=1">Link 1</a> |
<a href="?q=2">Link 2</a> |
<a href="?q=3">Link 3</a>
執行結果:
第一次連入 http://localhost:5000/
時,就被放入 Server 快取中,後續的 Request 全部都是從 Server 快取回應,所以不會進到 Action,自然不會有 Action 中的 Log 資訊。
嘗試在瀏覽器一直按 F5
刷新頁面,會發現根本不從 Server 快取拿結果,而是每次都重新跟 Action 拿新資料。這是正常的行為,因為要使用 Server 快取有條件的限制。
要使用 Server 快取,必須要達成以下條件:
GET
或 HEAD
。Authorization
。Cache-Control
值必須是 public
。F5
刷新頁面不會帶 Cache-Control
,所以使用 Server 快取條件不成立)
Set-Cookie
。Vary
值不能為 *
。IHttpSendFileFeature
。no-store
。MaximumBodySize
。SizeLimit
。如果用過 ASP.NET 的
[OutputCache]
,千萬不要以為[ResponseCache]
跟它是一樣的東西。
[ResponseCache]
多了上面一連串的必備條件...
(我也為此卡了一陣子,還把 Source Code Checkout 下來 Debug...)
Response caching in ASP.NET Core