【问题标题】:Caching full response on the server在服务器上缓存完整响应
【发布时间】:2020-05-09 15:10:09
【问题描述】:

这是一个非常小的 Razor 页面示例:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<h1>
    @DateTime.Now.ToString()
</h1>

//model
public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> _logger;

    public IndexModel(ILogger<IndexModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {

    }
}

如果我使用此代码,时间将每 30 秒更新一次,这是预期的:

<cache expires-after="TimeSpan.FromSeconds(30)">
    <h1>
        @DateTime.Now.ToString()
    </h1>
</cache>

但是,将ResponseCache 属性添加到模型并不会这样做:

[ResponseCache(Duration = 30)]
public class IndexModel : PageModel

在做了一些研究之后,似乎该属性只向客户端发送了适当的标头,要求它缓存内容。如何将整个响应存储在内存中,以便当用户请求特定页面时,服务器只发送缓存的响应并消除再次计算结果的过程?

另外,使用&lt;cache&gt; 标签助手,我找不到使缓存条目无效的方法。因此,对我来说,一个场景是将每个页面在内存中缓存 30 天,如果我在管理面板上更改某些内容,我将使该特定项目的缓存无效,以便下一个请求会产生新的结果。我曾经在 Asp.Net MVC 3+ 上执行此操作,但在 Asp.Net Core 3.1 中找不到任何实现相同结果的方法

【问题讨论】:

  • 你可以使用Redis,或者NCache来存储数据。在你可以使 redis 或 ncache 失效之后
  • 您是否尝试过使用 标签的 vary-by 属性?对其引用的对象的任何更改都应使标记的缓存内容无效。
  • @Onur 我更喜欢使用框架本身,但如果不可能,请发布示例代码。谢谢
  • @JohnM 我可以使用它,但我想在它遇到“OnGetAsync()”之前缓存整个页面,因为大部分瓶颈来自从数据库获取数据,而不是渲染部分。虽然我可以缓存一个动作,但这似乎是个坏主意。此外,使用“vary-by”仍然会保留内存中的缓存数据而不是清除它。
  • @AlirezaNoori 我正在尝试github.com/VahidN/EFCoreSecondLevelCacheInterceptor 使用自动配置选项缓存数据库访问,以默认缓存所有内容,并在需要时让缓存失效。我希望它有效...

标签: asp.net asp.net-core caching asp.net-core-mvc razor-pages


【解决方案1】:

从您的问题看来,您可能需要推出自己的版本

如何将整个响应存储在内存中,以便当用户询问时 对于特定页面,服务器只发送缓存的响应和 消除再次计算结果的过程?

查看源码 https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ResponseCacheAttribute.cs

还有

https://github.com/aspnet/Mvc/blob/d8c6c4ab34e1368c1b071a01fcdcb9e8cc12e110/src/Microsoft.AspNetCore.Mvc.Core/Internal/ResponseCacheFilter.cs

它似乎只设置标题。

您可以像这样实现自己的缓存版本

https://www.devtrends.co.uk/blog/custom-response-caching-in-asp.net-core-with-cache-invalidation

参见上述示例中的 CachedPage 类。

【讨论】:

    【解决方案2】:

    编辑:不,它不起作用(我无法删除此答案)。

    https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/performance/caching/middleware/samples/3.x/ResponseCachingMiddleware

    浏览器通常会在重新加载时添加缓存控制标头,以防止 提供缓存页面的中间件。

    因此,它不起作用,除了使用特制请求的机器请求之外,我看不出它还有什么用处。

    使用允许设置请求标头的开发人员工具 明确的,例如 Fiddler 或 Postman。


    我还没有测试过,但看起来“响应缓存中间件”可能是答案。

    https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-3.1

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

    ASP.NET Core 中的响应缓存中间件:

    https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1

    中间件确定响应何时可缓存,存储 响应,并提供来自缓存的响应。

    不过,您不会总是得到缓存的响应。

    中间件遵守 HTTP 1.1 缓存规则 规格。规则需要缓存来兑现有效的 客户端发送的 Cache-Control 标头。根据规范,一个 客户端可以使用 no-cache 标头值发出请求并强制 服务器为每个请求生成一个新的响应。现在, 使用时,开发人员无法控制此缓存行为 中间件,因为中间件遵守官方缓存 规范。

    另外

    只应为不会更改的内容启用缓存 关于用户的身份或用户是否已登录。

    【讨论】:

    • 这正是我的问题。有趣的是,在 Asp.Net MVC 5 中,我可以通过框架本身轻松做到这一点
    • 标签助手在部分视图中工作正常,总比没有好。我还使用github.com/VahidN/EFCoreSecondLevelCacheInterceptor 缓存数据库访问
    猜你喜欢
    • 2011-10-09
    • 1970-01-01
    • 2018-06-27
    • 2014-08-22
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多