ASP.NET Core 中的响应缓存

作者: John LuoRick AndersonSteve Smith

查看或下载示例代码如何下载

响应缓存可减少客户端或代理对 web 服务器发出的请求数。 响应缓存还减少了 web 服务器生成响应所需的工作量。 响应缓存由指定你希望客户端、代理和中间件缓存响应的方式的标头控制。

ResponseCache 属性参与设置响应缓存标头。 客户端和中间代理应遵循HTTP 1.1 Caching 规范下的缓存响应的标头。

对于遵循 HTTP 1.1 Caching 规范的服务器端缓存,请使用响应 Caching 中间件。 中间件可以使用 ResponseCacheAttribute 属性来影响服务器端的缓存行为。

基于 HTTP 的响应缓存

HTTP 1.1 Caching 规范介绍了 Internet 缓存的行为方式。 用于缓存的主 HTTP 标头是 缓存控制,它用于指定缓存 指令。 指令控制缓存行为作为请求从客户端发送到服务器,而作为响应,使其从服务器到客户端的方式。 请求和响应会在代理服务器之间移动,并且代理服务器还必须符合 HTTP 1.1 Caching 规范。

Cache-Control下表显示了常见的指令。

指令 操作
公共 缓存可以存储响应。
private 共享缓存不能存储响应。 专用缓存可以存储和重用响应。
最大期限 客户端不接受其期限大于指定秒数的响应。 示例: max-age=60 (60 秒) , max-age=2592000 (1 个月)
no-cache 请求时:缓存不能使用存储的响应来满足请求。 源服务器重新生成客户端的响应,中间件更新其缓存中存储的响应。

响应:在 源服务器上没有验证的后续请求不得使用响应。
无-商店 请求时:缓存不能存储请求。

响应:缓存不能存储响应的任何部分。

下表显示了在缓存中扮演角色的其他缓存标头。

标头 函数
年龄 在源服务器上生成或成功验证响应以来的时间量(以秒为单位)。
Expires 响应被视为过时的时间。
存在,以便向后兼容 HTTP/1.0 缓存以设置 no-cache 行为。 如果该 Cache-Control 标头存在,则将 Pragma 忽略该标头。
指定不能发送缓存的响应,除非 Vary 缓存响应的原始请求和新请求中的所有标头字段都匹配。

基于 HTTP 的缓存遵从请求 Cache-Control 指令

Cache-Control 标头的 HTTP 1.1 Caching 规范要求使用缓存来服从 Cache-Control 客户端发送的有效标头。 客户端可以使用 no-cache 标头值发出请求,并强制服务器为每个请求生成新的响应。

Cache-Control如果考虑 HTTP 缓存的目标,则始终考虑客户端请求标头是有意义的。 在官方规范下,缓存旨在减少在客户端、代理和服务器网络中满足请求的延迟和网络开销。 它不一定是控制源服务器上的负载的一种方法。

当使用响应 Caching 中间件时,不存在对此缓存行为的开发人员控制,因为中间件遵循官方缓存规范。 支持使用 输出缓存 来更好地控制服务器负载是 ASP.NET Core 未来版本的设计方案。 有关详细信息,请参阅Add support for Output Caching (dotnet/aspnetcore #27387)

ASP.NET Core 中的其他缓存技术

内存中缓存

内存中缓存使用服务器内存来存储缓存的数据。 这种类型的缓存适用于单个服务器或使用 粘滞会话 的多台服务器。 粘滞会话表示来自客户端的请求始终路由到同一服务器进行处理。

有关详细信息,请参阅 ASP.NET Core 中的内存中缓存

分布式缓存

当应用程序托管在云或服务器场中时,使用分布式缓存将数据存储在内存中。 缓存在处理请求的服务器之间共享。 如果客户端的缓存数据可用,则客户端可以提交由组中的任何服务器处理的请求。 ASP.NET Core 适用于 SQL Server、 RedisNCache分布式缓存。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存

缓存标记帮助程序

使用缓存标记帮助程序从 MVC 视图或页面缓存内容 Razor 。 缓存标记帮助程序使用内存中缓存来存储数据。

有关详细信息,请参阅 ASP.NET Core MVC 中的缓存标记帮助程序

分布式缓存标记帮助程序

Razor使用分布式缓存标记帮助程序在分布式云和 web 场方案中,通过 MVC 视图或页面缓存内容。 分布式缓存标记帮助程序使用 SQL Server、 RedisNCache来存储数据。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存标记帮助程序

ResponseCache 特性

ResponseCacheAttribute指定在响应缓存中设置适当的标头所需的参数。

警告

禁用包含经过身份验证的客户端信息的内容的缓存。 只应为不会根据用户的身份更改或用户是否已登录的内容启用 Caching。

VaryByQueryKeys 根据给定的查询键列表的值,改变存储的响应。 当提供了的单个值时 * ,中间件将根据所有请求查询字符串参数来改变响应。

必须启用响应 Caching 中间件才能设置 VaryByQueryKeys 属性。 否则,会引发运行时异常。 此属性没有相应的 HTTP 标头 VaryByQueryKeys 。 属性是一个 HTTP 功能,由响应 Caching 中间件进行处理。 对于用于缓存响应的中间件,查询字符串和查询字符串值必须与上一个请求匹配。 例如,请考虑下表中显示的请求和结果的顺序。

请求 结果
http://example.com?key1=value1 从服务器返回的。
http://example.com?key1=value1 从中间件返回。
http://example.com?key1=value2 从服务器返回的。

第一个请求由服务器返回,并缓存在中间件中。 第二个请求是由中间件返回的,因为查询字符串与上一个请求匹配。 第三个请求不在中间件缓存中,因为查询字符串值与以前的请求不匹配。

ResponseCacheAttribute用于通过) (配置和创建 IFilterFactory Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilterResponseCacheFilter执行更新相应 HTTP 标头和响应功能的工作。 筛选器:

  • 删除、和的任何现有标头 Vary Cache-Control Pragma
  • 根据 中设置的属性写出相应的标头 ResponseCacheAttribute
  • 如果设置了 ,则更新响应缓存 HTTP VaryByQueryKeys 功能。

不同

只有在设置 属性时,才 VaryByHeader 写入此标头。 属性设置为 Vary 属性的值。 下面的示例使用 VaryByHeader 属性:

[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Cache1Model : PageModel
{

使用示例应用,使用浏览器的网络工具查看响应标头。 以下响应标头随 Cache1 页面响应一起发送:

Cache-Control: public,max-age=30
Vary: User-Agent

NoStore 和 Location.None

NoStore 替代大多数其他属性。 当此属性设置为 时 trueCache-Control 标头设置为 no-store 。 如果 Location 设置为 None

  • Cache-Control 设置为 no-store,no-cache
  • Pragma 设置为 no-cache

如果 NoStore 为 且 为 false Location None ,则 和 设置为 Cache-Control Pragma no-cache

NoStore 对于错误页, true 通常将 设置为 。 示例应用中的 Cache2 页生成响应标头,指示客户端不存储响应。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class Cache2Model : PageModel
{

示例应用返回包含以下标头的 Cache2 页:

Cache-Control: no-store,no-cache
Pragma: no-cache

位置和持续时间

若要启用缓存, Duration 必须设置为正值,并且必须设置为 (LocationAny Client) 。 框架将 Cache-Control 标头设置为位置值,后跟 max-age 响应的 。

Location和 的选项 Any Client 分别转换为 Cache-Controlpublicprivate 标头值。 如 NoStore 和 Location.None 部分所述,将 设置为 同时 Location 将 和 None Cache-Control Pragma 标头设置为 no-cache

Location.Any (设置为) 表示客户端或任何中间代理可以缓存值,包括中间 Cache-Control publicCaching响应

Location.Client (设置为 Cache-Control) private 表示 只有客户端 可以缓存值。 中间缓存不应缓存值,包括中间Caching响应

缓存控制标头仅指导客户端和中间代理何时以及如何缓存响应。 不保证客户端和代理将遵守HTTP 1.1Caching规范。 中间Caching的响应始终遵循规范所布局的缓存规则。

以下示例显示示例应用中的 Cache3 页面模型,以及通过设置 并保留默认值而 Duration 生成的 Location 标头:

[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public class Cache3Model : PageModel
{

示例应用返回包含以下标头的 Cache3 页:

Cache-Control: public,max-age=10

缓存配置文件

在 中设置 MVC/Pages 时,可以将缓存配置文件配置为选项,而不是在许多控制器操作属性上复制响应 Razor 缓存设置 Startup.ConfigureServices 。 在引用的缓存配置文件中发现的值由 用作默认值,并且由属性上指定的任何 ResponseCacheAttribute 属性替代。

设置缓存配置文件。 以下示例演示示例应用的 中的 30 秒缓存配置文件 Startup.ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("Default30",
            new CacheProfile()
            {
                Duration = 30
            });
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("Default30",
            new CacheProfile()
            {
                Duration = 30
            });
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

示例应用的 Cache4 页面模型引用 Default30 缓存配置文件:

[ResponseCache(CacheProfileName = "Default30")]
public class Cache4Model : PageModel
{

ResponseCacheAttribute可以应用于:

  • Razor Pages:特性不能应用于处理程序方法。
  • MVC 控制器。
  • MVC 操作方法:方法级属性替代类级属性中指定的设置。

缓存配置文件应用于 Cache4 页面响应的结果 Default30 标头:

Cache-Control: public,max-age=30

其他资源