首页 文章

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

提问于
浏览
1

我想在asp.net core 2.0中使用服务器端响应缓存(输出缓存)并找到关于Response Caching Middleware的内容,并希望尝试使用全新的asp.core mvc项目 .

以下是上面链接的描述,这让我觉得这可以像输出缓存一样使用 .

中间件确定响应何时可缓存,存储响应以及从缓存提供响应 .

这是我的startup.cs的样子 .

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCaching();
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCaching();

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

这是HomeController.cs

[ResponseCache(Duration = 60)]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    }

    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";

        return View();
    }

    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}

_Layout.cshtml文件底部还有一个时间戳,所以我可以告诉页面何时呈现,如下所示 .

<p>&copy; 2018 - ResponseCachingMiddleware - @DateTime.UtcNow</p>

Cache-Control Headers 看起来很好,这是我加载页面时在 Headers 中得到的,但时间戳每秒刷新一次 .

Cache-Control:public,max-age=60

我从MS文档中理解的是响应缓存中间件是服务器端缓存机制,它负责缓存响应,而Response Caching似乎只是一个操作缓存响应头的过滤器 .

无法判断我的理解或代码是否有问题,我想抱怨自从我开始使用ASP.Net Core进行原型设计以来,我经常会这样 . 也许你也可以建议更好的资源作为一个侧面话题 .

我已经在ASP.NET Core 2.0 - Http Response Caching Middleware - Nothing cached之前查看了这篇文章

也检查了这一点,但似乎唯一的区别是我正在使用mvc . https://github.com/aspnet/ResponseCaching/blob/dev/samples/ResponseCachingSample/Startup.cs

谢谢

编辑:我在输出窗口中看到下面的消息,除了我已经检查过响应缓存中间件的几个地方之外,在谷歌上找不到任何关于它的信息 .

Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware:信息:无法为此请求缓存响应 .

注意:我希望我可以创建#response -caching-middleware标签 . 不确定#responsecache是否相关 .

3 回答

  • 1

    我最近也有同样的困惑 .

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

    不幸的是,调试服务器端的ResponseCaching很棘手,因为它有奇怪的规则并且没有足够的日志记录 . 在我的情况下,我删除了微软的源代码,逐步完成它并找到我的代码问题 .

    您在输出窗口“无法为此请求缓存响应”中找到的注释是一个线索 .

    服务器端缓存请求有两个部分 . 服务器必须在第一次请求URL时填充缓存 . 它将在第二次请求时提供缓存版本 . 注意错误消息何时显示,如果是在第一个或第二个请求上 . 这将告诉您它是否无法存储在缓存中或无法从缓存中检索 .

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

    你的“Cache-Control:public,max-age = 60” Headers 应该符合这些规则 .

    我的猜测是你实际上有它工作,但不知道如何正确测试它 . 本期中提到了一个反直觉的ResponseCaching部分:https://github.com/aspnet/Home/issues/2607本质上,如果浏览器发送无缓存或无存储头(当您按CTRL F5或打开调试器工具时),ASP.Net Core 's ResponseCaching will honor the browser' s请求并重新生成响应 .

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

    测试这种方法的方法是在请求之间清除浏览器缓存(或切换到隐身),而不是使用CTRL F5 .

    另外,尊重no-cache / no-store请求标头可能是一个糟糕的设计选择,因为ASP.Net Core的ResponseCache很可能被拥有响应的服务器使用,而不是像CDN /那样的中间缓存ISP . 我已经扩展了基本的ResponseCache,并选择了禁用这些头文件(以及将缓存序列化为磁盘,而不是仅限内存) . 它是默认缓存的简单替代品 .

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

    还有一些其他的问题与ResponseCaching有关,你可能已经在你发布的博客网址中看到了这些问题 . 使用set-cookie的经过身份验证的请求和响应将不会被缓存 . 只缓存使用GET或HEAD方法的请求 . 如果QueryString不同,它将创建一个新的缓存条目 . 此外,如果请求的某些条件与先前缓存的不同,通常您会想要一个“Vary”标头来阻止缓存请求(例如:user-agent,accept-encoding等) . 最后,如果一个中间件处理一个请求,它将在以后的中间件短路 . 确保你的app.UseResponseCaching()在app.UseMVC()之前注册

  • -1

    我遇到了同样的问题,我正要把它拉过来,我设置 app.UseResponseCaching(); 以及 services.AddResponseCaching(); 并在我的操作之上添加 ResponseCache ,就像微软官方Docs中所说的那样,尽管设置了 cache-controll Headers 正确地响应从服务器返回但仍未在服务器端缓存 .

    在这个问题上经过几个小时的出汗后,我想出了问题出现的原因以及为什么没有任何缓存在服务器上 .

    默认情况下,浏览器会为请求将 cache-controll 值设置为 max-age=0 (如果请求不是由后向或前向引起的),即使您在响应中正确设置了 cache-controller ,也可以在您的操作(或控制器)之上添加 ResponseCache 属性,因为 cache-controller 发送了请求设置为 max-age=0 ,服务器无法缓存响应,我认为这必须添加到 Response Caching 限制列表中

    无论如何,您可以通过在调用 app.UseResponseCaching(); 之前添加几行代码来覆盖浏览器默认行为,另一方面,您需要在调用 app.UseResponseCaching(); 之前添加自定义中间件来修改请求 cache-control 标头值 .

    看下面的代码,为我工作也希望为你工作

    app.Use(async (ctx, next) =>
            {
                ctx.Request.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
                {
                    Public = true,
                    MaxAge = TimeSpan.FromSeconds(60)
                };
                await next();
            }
                );
            app.UseResponseCaching();
    

    为确保ResponseCaching按预期工作,您也可以使用邮递员,但必须在设置中将 'Send no-cache Header' 设置为 off ,请参见下图

    enter image description here

  • 4

    如果 Cache-Control 标头正在通过,则它可以从该角度查看所有服务器的所有内容 . 客户端最终决定是否实际缓存资源 . 发送 Headers 不会强制客户端执行任何操作;事实上,服务器通常不能强迫客户端做任何事情 .

相关问题