且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ASP.Net Core 2.0-ResponseCaching中间件-服务器上不缓存

更新时间:2023-02-16 10:45:56

我最近也有同样的困惑.

I had this same confusion recently.

ASP.Net Core的ResponseCaching确实提供了客户端缓存(通过HTTP响应标头)和服务器端(如果响应在缓存中,则通过内存缓存的中间件使其他中间件短路).服务器端部分读取HTTP响应缓存头,以确定是否应进行服务器端缓存(类似于ISP或CDN可能执行的操作).

ASP.Net Core's ResponseCaching does provide both client-side caching (through HTTP response headers) & server-side (through a memory cache'd middleware that short-circuits other middlewares if the response is in the cache). The server-side portion reads the HTTP response cache headers to determine if it should do server-side caching (similar to what an ISP or CDN might do).

不幸的是,调试服务器端ResponseCaching很棘手,因为它具有怪异的规则&没有足够的日志记录.就我而言,我提取了Microsoft的源代码以逐步完成&找到我的代码存在的问题.

Unfortunately, debugging the server-side ResponseCaching is tricky because it has weird rules & there's not adequate logging. In my case I pulled down Microsoft's source code to step through it & find the issue with my code.

您在输出窗口中找到的注释无法为此请求缓存响应"是一个提示.

The note you found in the output window "The response could not be cached for this request" is a clue.

请求的服务器端缓存分为两部分.服务器必须在第一次请求url时准备好缓存.它将第二次请求缓存的版本.请注意错误消息出现的时间(如果是第一个或第二个请求).它将告诉您它是否无法存储在缓存中,或者是否无法从缓存中检索.

There's 2 parts to the server-side caching of a request. The server has to prime the cache the first time the url is requested. It will serve the cached version the 2nd time it's requested. Pay attention to when the error message shows up, if it's on the 1st or 2nd request. That'll tell you if it couldn't be stored in the cache or if it couldn't be retrieved from the cache.

存储和存储的规则检索在此源代码文件中: https://github./ResponseCaching/blob/3bf5f6a1ce69b65c998d6f5c739822a9bed4a67e/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachingPolicyProvider.cs

The rules for both storage & retrieval are in this source code file: https://github.com/aspnet/ResponseCaching/blob/3bf5f6a1ce69b65c998d6f5c739822a9bed4a67e/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachingPolicyProvider.cs

您的"Cache-Control:public,max-age = 60"标头应与这些规则完全匹配.

Your "Cache-Control:public,max-age=60" header should match these rules just fine.

我的猜测是您实际上已在运行它,但不知道如何正确测试它. 在本期中提到了ResponseCaching的违反直觉的部分: https://github.com/aspnet/Home/issues/2607 本质上,如果浏览器发送无缓存或无存储标头(当您按CTRL + F5或打开调试器工具时),ASP.Net Core的ResponseCaching将接受浏览器的请求.重新生成响应.

My guess is you actually had it working, but didn't know how to test it correctly. There is a counter-intuitive portion of ResponseCaching noted in this issue: https://github.com/aspnet/Home/issues/2607 Essentially, if the browser sends a no-cache or no-store header (when you hit CTRL+F5 or have your debugger tools open), ASP.Net Core's ResponseCaching will honor the browser's request & re-generate the response.

因此,要测试您的代码是否正常工作,您可能加载了页面,从而启动了缓存,然后按CTRL + F5强制刷新浏览器&您希望服务器端以缓存的条目作为响应,而不是运行WebAPI代码.但是,它尊重无缓存请求标头&绕过缓存(并在输出日志中写入该消息).

So, to test if your code was working you probably loaded the page, which primed the cache, then you hit CTRL+F5 to force-refresh your browser & you expected the server-side to respond with a cached entry rather than running your WebAPI code. However, it honored the no-cache request header & bypassed the cache (& wrote that message in your output log).

测试此方法的方法是清除请求之间的浏览器缓存(或切换为隐身模式),而不是使用CTRL + F5.

The way to test this would be to clear your browser cache in-between requests (or switch to incognito), rather than using CTRL+F5.

另一方面,由于ASP.Net Core的ResponseCache很可能会由拥有响应的服务器而不是像中间缓存这样的服务器使用,因此遵守no-cache/no-store请求标头可能是一个糟糕的设计选择. CDN/ISP.我已经对基本ResponseCache进行了扩展,提供了一个禁用这些标头的选项(以及将缓存序列化到磁盘上,而不是仅在内存中).这是默认缓存的便捷替代.

On a side note, honoring the no-cache/no-store request headers was probably a poor design choice since ASP.Net Core's ResponseCache will most likely be used by a server who owns the response, rather than an intermediary cache like a CDN/ISP. I've extended the base ResponseCache with an option to disable honoring these headers (as well as serialize the cache to disk, rather than in-memory only). It's an easy drop-in replacement for the default cache.

您可以在这里找到我的扩展名: https://github.com/speige/AspNetCore.ResponseCaching.Extensions https://www.nuget.org/packages/AspNetCore.ResponseCaching.Extensions

You can find my extension here: https://github.com/speige/AspNetCore.ResponseCaching.Extensions https://www.nuget.org/packages/AspNetCore.ResponseCaching.Extensions

还有其他一些带有ResponseCaching的陷阱,请注意您在发布的博客URL中可能已经读过的内容.已验证的请求和带有set-cookie的响应将不会被缓存.仅使用GET或HEAD方法的请求将被缓存.如果QueryString不同,它将创建一个新的缓存条目.另外,通常,如果请求的某些条件与先前缓存的请求不同(例如:用户代理,接受编码等),通常您会希望使用"Vary"标头来防止缓存.最后,如果中间件处理了请求,它将使后面的中间件短路.确保在app.UseMVC()之前注册了app.UseResponseCaching()

There are also a few other other gotchas with ResponseCaching to watch out for which you may have already read about in the blog urls you posted. Authenticated requests & responses with set-cookie won't be cached. Only requests using GET or HEAD method will be cached. If the QueryString is different, it'll make a new cache entry. Also, usually you'll want a "Vary" header to prevent caching if certain conditions of a request differ from the previously-cached request (example: user-agent, accept-encoding, etc). Finally, if a Middleware handles a request it'll short-circuit later Middlewares. Make sure your app.UseResponseCaching() is registered before app.UseMVC()