ASP.Net Core 2.0 - ПО промежуточного слоя ResponseCaching - Не кэширование на сервере

Я хочу использовать кеширование ответов на стороне сервера (кеш вывода) с asp.net core 2.0 и узнал о ПО промежуточного слоя кэширования ответов и хотел попробовать его с новым проектом 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 кажутся в порядке, это то, что я получаю в заголовках, когда загружаю страницу, но отметка времени обновляется при каждом обновлении каждую секунду.

Cache-Control:public,max-age=60

Из документации MS я понимаю, что ПО промежуточного слоя кэширования ответов - это механизм кэширования на стороне сервера, который заботится о кэшировании ответа, пока Кэширование ответов кажется просто фильтром для управления заголовками ответов для кэширования.

Не могу сказать, что что-то не так с моим пониманием или кодом, и я хочу пожаловаться, что чувствую это слишком часто с тех пор, как начал создавать прототип с помощью ASP.Net Core. Может быть, вы могли бы также предложить лучшие ресурсы в качестве дополнительной темы.

Я просмотрел этот пост перед ASP. NET Core 2.0 - ПО промежуточного слоя для кэширования ответов HTTP - ничего не кэшируется

Также проверил это, но похоже, единственная разница в том, что я использую mvc. https://github.com/aspnet/ResponseCaching/blob/dev/samples/ResponseCachingSample/Startup.cs

Спасибо

Изменить: я вижу сообщение ниже в окне вывода, не могу найти ничего об этом в Google, кроме нескольких мест, которые я уже проверил для промежуточного программного обеспечения кеширования ответов.

Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware: Информация: не удалось кэшировать ответ для этого запроса.

Примечание. Я хотел бы создать тег # response-caching-middleware. Не уверен, что #responsecache актуален.


person Engin    schedule 12.01.2018    source источник


Ответы (3)


Недавно у меня было такое же замешательство.

ResponseCaching в ASP.Net Core обеспечивает как кэширование на стороне клиента (через заголовки ответов HTTP), так и на стороне сервера (через промежуточное ПО с кешем памяти, которое замыкает другие промежуточные ПО, если ответ находится в кеше). Серверная часть считывает заголовки кеша ответов HTTP, чтобы определить, следует ли выполнять кэширование на стороне сервера (аналогично тому, что может сделать ISP или CDN).

К сожалению, отладка серверного ResponseCaching затруднена, потому что у нее есть странные правила и нет адекватного ведения журнала. В моем случае я взял исходный код Microsoft, чтобы пройти через него и найти проблему с моим кодом.

Заметка, которую вы нашли в окне вывода «Не удалось кэшировать ответ для этого запроса», является подсказкой.

Кэширование запроса на стороне сервера состоит из двух частей. Сервер должен заполнить кеш при первом запросе URL-адреса. Он будет обслуживать кешированную версию при втором запросе. Обратите внимание, когда появляется сообщение об ошибке, если это 1-й или 2-й запрос. Это скажет вам, нельзя ли его сохранить в кеше или получить из кеша.

Правила как для хранения, так и для извлечения находятся в этом файле исходного кода: https://github.com/aspnet/ResponseCaching/blob/3bf5f6a1ce69b65c998d6f5c739822a9bed4a67e/src/Microsoft.AspNetCoreicyPolicy.ResponseCash/ResponseResponse.=

Ваш заголовок «Cache-Control: public, max-age = 60» должен полностью соответствовать этим правилам.

Я предполагаю, что у вас это действительно работало, но вы не знали, как правильно это проверить. В этой проблеме отмечена противоречащая интуиции часть ResponseCaching: https://github.com/aspnet/Home/issues/2607 По сути, если браузер отправляет заголовок без кеширования или без сохранения (когда вы нажимаете CTRL + F5 или открываете инструменты отладчика), ResponseCaching ASP.Net Core будет учитывать запрос браузера. & повторно сгенерировать ответ.

Итак, чтобы проверить, работает ли ваш код, вы, вероятно, загрузили страницу, которая загрузила кеш, затем вы нажимаете CTRL + F5, чтобы принудительно обновить свой браузер, и вы ожидали, что серверная сторона ответит кешированной записью, а не запустит ваш WebAPI код. Однако он принял во внимание заголовок запроса без кеширования и обошел кеш (и записал это сообщение в ваш выходной журнал).

Способ проверить это - очистить кеш браузера между запросами (или переключиться в режим инкогнито), а не использовать CTRL + F5.

С другой стороны, соблюдение заголовков запросов без кеширования / без хранения, вероятно, было плохим выбором дизайна, поскольку ResponseCache ASP.Net Core, скорее всего, будет использоваться сервером, которому принадлежит ответ, а не промежуточным кешем, таким как CDN / Интернет-провайдер. Я расширил базовый ResponseCache, добавив в него возможность отключить соблюдение этих заголовков (а также сериализовать кеш на диск, а не только в памяти). Это простая замена кеш-памяти по умолчанию.

Вы можете найти мое расширение здесь: https://github.com/speige/AspNetCore.ResponseCaching.Extensions https://www.nuget.org/packages/AspNetCore.ResponseCaching.Extensions < / а>

Есть также несколько других ошибок с ResponseCaching, о которых вы, возможно, уже читали в опубликованных вами URL-адресах блога. Запросы и ответы, проверенные с помощью set-cookie, не будут кэшироваться. Кэшируются только запросы, использующие метод GET или HEAD. Если QueryString отличается, будет создана новая запись в кеше. Кроме того, обычно вам понадобится заголовок «Vary», чтобы предотвратить кеширование, если определенные условия запроса отличаются от ранее кэшированного запроса (пример: user-agent, accept-encoding и т. Д.). Наконец, если промежуточное ПО обрабатывает запрос, оно позже закоротит промежуточное ПО. Убедитесь, что ваше приложение app.UseResponseCaching () зарегистрировано до app.UseMVC ()

person Devin Garner    schedule 16.02.2018
comment
Спасибо за развернутый ответ. Я отказался от этой проблемы на некоторое время после того, как нашел другое решение, но я проверю это, как только вернусь к ней. То, что я тестировал неправильно, имеет больше смысла, чем функциональность, которой не было. - person Engin; 04.09.2018
comment
@DevinGarner изучил ваш код, и вы должны зарегистрировать исключение (потому что оно есть). Кстати, вам следует провести тест производительности вашего кода по сравнению с кешированием ответов по умолчанию. Ваша реализация довольно медленная :) и должна поддерживать любой IResponseCacheEntry. С Уважением. - person Fab; 23.02.2019
comment
Спасибо за обзор кода @Fab, если у вас есть время, отправьте запрос на перенос с вашими улучшениями. Спасибо! - person Devin Garner; 25.02.2019
comment
Слава богу, я дочитал твой ответ до конца. Вызов app.UseResponseCaching(); перед app.UseMvc(); сделал свое дело! - person Jérôme MEVEL; 19.03.2019
comment
Microsoft отчаянно нужно сообщить нам, какое правило было нарушено, что препятствовало кешированию. - person Arrow_Raider; 31.03.2020

У меня была та же проблема, я собирался натянуть на нее волосы, я установил app.UseResponseCaching();, а также services.AddResponseCaching(); и добавил ResponseCache поверх своего действия точно так же, как было сказано в официальных документах Microsoft, несмотря на то, что заголовок cache-controll был установлен правильно, когда ответ возвращается с сервера, но на стороне сервера все еще ничего не кешируется.

После пары часов размышлений над этой проблемой я понял, где возникает проблема и почему на сервере ничего не кешируется.

Браузеры по умолчанию устанавливают значение cache-controll на max-age=0 для запроса (если запрос не вызван обратным или прямым пересылкой), даже если вы правильно задали cache-controller в своем ответе, добавив атрибут ResponseCache поверх вашего действия (или контроллера), поскольку cache-controller отправлено для запроса установлено значение max-age=0, сервер не может кэшировать ответ, я думаю, это также необходимо добавить в список ограничений кэширования ответов

В любом случае вы можете переопределить поведение браузера по умолчанию, добавив несколько строк кода прямо перед вызовом app.UseResponseCaching();, с другой стороны, вам нужно добавить настраиваемое промежуточное ПО для изменения значения заголовка запроса cache-control перед вызовом app.UseResponseCaching();.

См. Код ниже, сработал для меня, надеюсь, сработает и для вас

 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 работает должным образом, вы также можете использовать почтальон, но для параметра «Отправить заголовок без кеширования» необходимо установить значение выкл, см. изображение ниже.

введите описание изображения здесь

person Code_Worm    schedule 10.08.2018
comment
Спасибо, я отказался от этой проблемы на некоторое время, но я скоро вернусь к ней и попробую. - person Engin; 04.09.2018
comment
@Engin счастливого кодирования :) - person Code_Worm; 05.09.2018
comment
Да, это сработало, если у кого-то есть ошибка компиляции, добавьте пространство имен Microsoft.AspNetCore.Http GetTypedHeaders () - это метод расширения - person Daniel; 07.11.2019
comment
Работает с вызовами веб-API, обратите внимание, что вы можете проверить окно вывода (для меня .net core 3.1): ResponseCachingMiddleware: информация: ответ был кэширован., ResponseCachingMiddleware: информация: обслуживание ответа из кеша. - person eugen; 19.08.2020

Если заголовок Cache-Control проходит, значит, он работает. Это все, что сервер может сделать с этой точки зрения. В конечном итоге клиент принимает решение, фактически кэшировать ресурс. Отправка заголовка не заставляет клиента что-либо делать; на самом деле сервер, как правило, не может заставить клиента что-либо сделать.

person Chris Pratt    schedule 12.01.2018
comment
Можете ли вы объяснить мне, в чем разница между ПО промежуточного слоя кэширования ответов и кэшированием ответов? Насколько я могу судить, вы описываете ответственность фильтра кэширования ответов. - person Engin; 12.01.2018
comment
Здесь ничего нет. Это две стороны одной медали. Промежуточное ПО - это то, что на самом деле выполняет работу, в то время как атрибут информирует промежуточное ПО о том, что оно должно делать на самом деле (т. Е. Установить max-age=60, потому что вы указали Duration = 60). Кэширование ответов, как правило, устанавливает только заголовок Cache-Control. Он ничего не делает для кеширования ответа на стороне сервера. И, как я уже сказал, клиент на 100% решает, действительно ли соблюдается заголовок. Если вы ищете кеширование на стороне сервера, вам необходимо использовать кеширование в памяти или распределенное кеширование. - person Chris Pratt; 12.01.2018
comment
См. Описание ПО промежуточного слоя кэширования ответов со страницы документации, на которую я ссылался. В нем четко указано, что он хранит и обслуживает ответы. Вы можете спутать это с кешированием ответов. - person Engin; 12.01.2018
comment
Я считаю, что фильтры кэширования ответов используются для первой цели ПО промежуточного слоя кэширования ответов, которая определяет, когда ответ кэшируется. - person Engin; 12.01.2018
comment
Описание вводит в заблуждение, граничит с неверным. Я думаю, это относится к тому, что клиент сохраняет ответ, но если это так, то он сформулирован крайне неудачно. Тем не менее, все, что он делает, это устанавливает заголовки кеша. В следующей строке даже говорится столько же, сколько и о том, что он делает, как о HTTP-кешировании. - person Chris Pratt; 12.01.2018
comment
Если вы просмотрите всю документацию, вы увидите, что ничего не упоминается, кроме различных установленных заголовков и значений. Никогда не упоминается фактическое хранилище на стороне сервера. Если вы посмотрите на реальный код, вы также ясно увидите, что он ничего не делает, кроме манипулирования заголовками. - person Chris Pratt; 12.01.2018
comment
Вы хотите сказать, что код предназначен для демонстрации функциональности промежуточного программного обеспечения кэширования ответов, когда он уже выполняет манипуляции с заголовками вручную? Это означает, что если я удалю промежуточное программное обеспечение, я получу точно такое же поведение, так какой здесь пример кода? - person Engin; 12.01.2018
comment
вы используете ядро ​​asp.net? - person Engin; 12.01.2018
comment
Я считаю, что код, который вручную меняет заголовки ответов, должен сообщить промежуточному программному обеспечению, что оно должно кэшироваться, поскольку в коде нет контроллера для добавления фильтров. - person Engin; 12.01.2018
comment
в окнах вывода также появляется сообщение об ошибке, которое вы можете увидеть в вопросе. он говорит Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware: Информация: ответ не может быть кэширован для этого запроса. все это заставляет меня думать, что промежуточное ПО действительно отвечает за кеширование. - person Engin; 12.01.2018
comment
Это так. Однако я думаю, вы упускаете суть. Это HTTP-кеширование. Это совместная работа сервера и клиента, при которой сервер определяет, что, как и когда можно кэшировать, и указывает это клиенту через заголовки HTTP. Клиент может выбрать кэширование ресурса в соответствии с предложениями сервера. Сервер здесь ничего не кеширует. Клиент делает кеширование. - person Chris Pratt; 13.01.2018
comment
По промежуточного слоя считывает атрибут, а затем соответственно добавляет заголовки HTTP. Вот и все. - person Chris Pratt; 13.01.2018
comment
Мне действительно не хватает сути, потому что это делает промежуточное программное обеспечение избыточным, особенно в примере кода, приведенном для самого промежуточного программного обеспечения, поскольку заголовки уже добавлены до промежуточного программного обеспечения. Извините, если я пытаюсь спорить с вами, я убежден вашим ответом, что он не будет кешироваться, но я все еще не уверен, что это что-то еще, например, оболочка для реализации вашего собственный кеш в памяти, для которого я не видел примеров кода. Хочу убедиться, что правильно написала ответ. Спасибо кучу. - person Engin; 13.01.2018
comment
Я не уверен, о чем вы говорите, но это промежуточное ПО добавляет эти заголовки. У него упрощенная задача, но у него есть работа, и если вы не добавите промежуточное ПО, вы не получите заголовки кеша. Тем не менее, промежуточное ПО добавляет заголовки по умолчанию, поэтому на самом деле вам не нужен атрибут на вашем контроллере / действии. Это просто, если вы хотите настроить значения по умолчанию. - person Chris Pratt; 13.01.2018
comment
Это неверный ответ. ResponseCaching в ASP.Net Core выполняет как кеширование на стороне клиента (через заголовки), так и кеширование на стороне сервера (аналогично OutputCache в предыдущих версиях ASP.Net). OP специально спрашивал, почему не работает кеширование на стороне сервера. - person Devin Garner; 16.02.2018
comment
@DevinGarner: Нет. Вы можете посмотреть исходник, если хотите. Это не так. Это просто HTTP-кеш. - person Chris Pratt; 16.02.2018
comment
@ChrisPratt Я прочитал источник. github.com/aspnet/ResponseCaching Я тоже успешно его использовал. Возможно, вы были правы насчет более ранней версии ResponseCaching ядра .NET, но он также был серверным кешем уже более года. - person Devin Garner; 16.02.2018