- 全球化与本土化
- 性能
- 高级
响应缓存在 ASP.NET Core
作者: John Luo、 Rick Anderson、 Steve Smith和Luke Latham
响应缓存可减少客户端或代理对 web 服务器发出的请求数。 响应缓存还减少了 web 服务器生成响应所需的工作量。 响应缓存由指定你希望客户端、代理和中间件缓存响应的方式的标头控制。
ResponseCache 属性参与设置响应缓存标头。 在HTTP 1.1 缓存规范下,客户端和中间代理应遵循用于缓存响应的标头。
对于遵循 HTTP 1.1 缓存规范的服务器端缓存,请使用响应缓存中间件。 中间件可以使用 ResponseCacheAttribute 属性来影响服务器端的缓存行为。
基于 HTTP 的响应缓存
HTTP 1.1 缓存规范描述了 Internet 缓存的行为方式。 用于缓存的主 HTTP 标头是缓存控制,它用于指定缓存指令。 指令控制缓存行为作为请求从客户端发送到服务器,而作为响应,使其从服务器到客户端的方式。 请求和响应在代理服务器之间移动,并且代理服务器还必须符合 HTTP 1.1 缓存规范。
下表显示了常见的 Cache-Control
指令。
Directive | 操作 |
---|---|
公用 | 缓存可以存储响应。 |
专用 | 共享缓存不能存储响应。 专用缓存可以存储和重用响应。 |
max-age | 客户端不接受其期限大于指定秒数的响应。 示例: max-age=60 (60秒)、max-age=2592000 (1个月) |
no-cache | 请求时:缓存不能使用存储的响应来满足请求。 源服务器重新生成客户端的响应,中间件更新其缓存中存储的响应。 响应:在源服务器上没有验证的后续请求不得使用响应。 |
no-store | 请求时:缓存不能存储请求。 响应:缓存不能存储响应的任何部分。 |
下表显示了在缓存中扮演角色的其他缓存标头。
Header | 函数 |
---|---|
年 | 在源服务器上生成或成功验证响应以来的时间量(以秒为单位)。 |
完 | 响应被视为过时的时间。 |
杂 | 存在,以便向后兼容 HTTP/1.0 缓存以设置 no-cache 行为。 如果 Cache-Control 标头存在,则将忽略 Pragma 标头。 |
大 | 指定不能发送缓存的响应,除非已缓存响应的原始请求和新请求中的所有 Vary 标头字段都匹配。 |
基于 HTTP 的缓存遵循请求缓存控制指令
缓存控制标头的 HTTP 1.1 缓存规范要求使用缓存来服从客户端发送的有效 Cache-Control
标头。 客户端可以使用 no-cache
标头值发出请求,并强制服务器为每个请求生成新的响应。
如果考虑 HTTP 缓存的目标,则始终考虑客户端 Cache-Control
请求标头是有意义的。 在官方规范下,缓存旨在减少在客户端、代理和服务器网络中满足请求的延迟和网络开销。 它不一定是控制源服务器上的负载的一种方法。
使用响应缓存中间件时,无开发人员对此缓存行为的控制,因为中间件遵循官方缓存规范。 中间件的计划增强功能是在决定为缓存的响应提供服务时,将中间件配置为忽略请求的 Cache-Control
标头的机会。 计划的增强功能提供了一种更好地控制服务器负载的机会。
在 ASP.NET Core 中其他缓存技术
内存中缓存
内存中缓存使用服务器内存来存储缓存的数据。 这种类型的缓存适用于单个服务器或使用粘滞会话的多台服务器。 粘滞会话表示来自客户端的请求始终路由到同一服务器进行处理。
有关更多信息,请参见缓存在内存中 ASP.NET Core。
分布式缓存
当应用程序托管在云或服务器场中时,使用分布式缓存将数据存储在内存中。 缓存在处理请求的服务器之间共享。 如果客户端的缓存数据可用,则客户端可以提交由组中的任何服务器处理的请求。 ASP.NET Core 适用于 SQL Server、 Redis和NCache分布式缓存。
有关更多信息,请参见ASP.NET Core 中的分布式缓存。
缓存标记帮助程序
使用缓存标记帮助程序从 MVC 视图或 Razor 页面缓存内容。 缓存标记帮助程序使用内存中缓存来存储数据。
有关更多信息,请参见ASP.NET Core MVC 中的缓存标记帮助程序。
分布式缓存标记帮助程序
使用分布式缓存标记帮助程序在分布式云和 web 场方案中,通过 MVC 视图或 Razor 页面缓存内容。 分布式缓存标记帮助程序使用 SQL Server、 Redis或NCache来存储数据。
有关更多信息,请参见ASP.NET Core 中的分布式缓存标记帮助程序。
ResponseCache 特性
ResponseCacheAttribute 指定在响应缓存中设置适当的标头所需的参数。
警告
禁用包含经过身份验证的客户端信息的内容的缓存。 只应为不会根据用户身份更改或用户是否已登录的内容启用缓存。
VaryByQueryKeys 根据给定的查询密钥列表值改变存储的响应。 如果提供了 *
的单个值,中间件将根据所有请求查询字符串参数来改变响应。
必须启用响应缓存中间件才能设置 "VaryByQueryKeys" 属性。 否则,会引发运行时异常。 VaryByQueryKeys 属性没有相应的 HTTP 标头。 属性是由响应缓存中间件处理的 HTTP 功能。 对于用于缓存响应的中间件,查询字符串和查询字符串值必须与上一个请求匹配。 例如,请考虑下表中显示的请求和结果的顺序。
请求 | 结果 |
---|---|
http://example.com?key1=value1 |
从服务器返回的。 |
http://example.com?key1=value1 |
从中间件返回。 |
http://example.com?key1=value2 |
从服务器返回的。 |
第一个请求由服务器返回,并缓存在中间件中。 第二个请求是由中间件返回的,因为查询字符串与上一个请求匹配。 第三个请求不在中间件缓存中,因为查询字符串值与以前的请求不匹配。
ResponseCacheAttribute 用于配置和创建(通过 IFilterFactory) Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter
。 ResponseCacheFilter
执行更新相应 HTTP 标头和响应功能的工作。 筛选器:
- 删除
Vary
、Cache-Control
和Pragma
的任何现有标头。 - 根据 ResponseCacheAttribute中设置的属性写出适当的标头。
- 如果设置 VaryByQueryKeys,则更新响应缓存 HTTP 功能。
大
仅当设置 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 重写大多数其他属性。 如果将此属性设置为 true
,则 Cache-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 设置为正值,Location 必须是 Any
(默认值)或 Client
。 框架将 Cache-Control
标头设置为位置值,后跟响应的 max-age
。
Location的 Any
和 Client
的选项分别转换为 public
和 private``Cache-Control
的标头值。 如NoStore部分中所述,将 Location 设置为 None
将 Cache-Control
和 Pragma
标头设置为 no-cache
。
Location.Any
(Cache-Control
设置为 public
)表示客户端或任何中间代理可以缓存值,包括响应缓存中间件。
Location.Client
(Cache-Control
设置为 private
)表示只有客户端可以缓存该值。 中间缓存不应缓存值,包括响应缓存中间件。
缓存控制标头仅向客户端和中间代理提供指导,以及如何缓存响应。 不保证客户端和代理将遵循HTTP 1.1 缓存规范。 响应缓存中间件始终遵循由规范布局的缓存规则。
下面的示例演示示例应用中的 Cache3 页模型以及通过设置 Duration 并保留默认 Location 值而生成的标头:
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)] public class Cache3Model : PageModel {
示例应用返回具有以下标头的 Cache3 页:
Cache-Control: public,max-age=10
缓存配置文件
在 Startup.ConfigureServices
中设置 MVC/Razor Pages 时,可以将缓存配置文件配置为选项,而不是对许多控制器操作属性复制响应缓存设置。 在引用的缓存配置文件中找到的值将用作 ResponseCacheAttribute 的默认值,并由特性上指定的任何属性重写。
设置缓存配置文件。 以下示例显示示例应用的 Startup.ConfigureServices
中的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 页面处理程序(类) – 特性不能应用于处理程序方法。
- MVC 控制器(类)。
- MVC 操作(方法) – 方法级特性覆盖类级特性中指定的设置。
Default30
缓存配置文件将生成的标头应用到 Cache4 页响应:
Cache-Control: public,max-age=30