ASP.Net Core 2.0 - промежуточное программное обеспечение ResponseCaching - не кэшируется на сервере
Я хочу использовать кэширование ответов на стороне сервера (выходной кеш) с ядром asp.net 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>© 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 имеет значение.
3 ответа
Если Cache-Control
заголовок проходит, потом работает. Это все, что сервер может сделать с этой точки зрения. В конечном итоге клиент принимает решение, действительно ли кешировать ресурс. Отправка заголовка не заставляет клиента что-либо делать; на самом деле сервер вообще не может заставить клиента что-либо делать.
У меня была та же проблема, я собирался натянуть на нее волосы, я бы поставил 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 вы также можете использовать почтальон, но в настройке необходимо отключить "Send no-cache Header", см. изображение ниже
У меня было то же самое замешательство недавно.
ResponseCaching ядра ASP.Net Core обеспечивает как кэширование на стороне клиента (через заголовки ответа HTTP), так и на стороне сервера (через промежуточное ПО кэша памяти, которое закорачивает другое промежуточное ПО, если ответ находится в кэше). Серверная часть считывает заголовки кэша ответов HTTP, чтобы определить, следует ли выполнять кэширование на стороне сервера (аналогично тому, что может делать ISP или CDN).
К сожалению, отладка ResponseCaching на стороне сервера является сложной задачей, поскольку в ней есть странные правила и нет адекватной регистрации. В моем случае я вытащил исходный код Microsoft, чтобы просмотреть его и найти проблему с моим кодом.
Заметка, которую вы нашли в окне вывода "Не удалось кэшировать ответ на этот запрос", является подсказкой.
Кэширование запроса на стороне сервера состоит из двух частей. Сервер должен заполнить кеш при первом запросе URL. Он будет обслуживать кэшированную версию во второй раз, когда он запрашивается Обратите внимание, когда появляется сообщение об ошибке, если оно находится на первом или втором запросе. Это скажет вам, если он не может быть сохранен в кеше или не может быть извлечен из кеша.
Правила для хранения и извлечения находятся в этом файле исходного кода: https://github.com/aspnet/ResponseCaching/blob/3bf5f6a1ce69b65c998d6f5c739822a9bed4a67e/src/Microsoft.AspNetCore.ResponseCaching/Internal/ResponseCachingPolicyProvider.cs
Ваш заголовок "Cache-Control:public,max-age=60" должен точно соответствовать этим правилам.
Полагаю, у вас все получилось, но вы не знали, как правильно это проверить. В этой проблеме отмечена нелогичная часть ResponseCaching: https://github.com/aspnet/Home/issues/2607 По сути, если браузер отправляет заголовок без кэша или без хранилища (когда вы нажимаете CTRL+F5 или откройте инструменты отладчика), ResponseCaching в ASP.Net Core выполнит запрос браузера и повторно сгенерирует ответ.
Итак, чтобы проверить, работает ли ваш код, вы, вероятно, загрузили страницу, которая заполнила кэш, затем вы нажали CTRL+F5, чтобы принудительно обновить ваш браузер, и вы ожидали, что серверная сторона ответит кэшированной записью, а не запустит ваш WebAPI. код. Тем не менее, он учитывал заголовок запроса no-cache и обошел кеш (и записал это сообщение в ваш выходной журнал).
Чтобы проверить это, нужно очистить кэш браузера между запросами (или переключиться на инкогнито), а не с помощью CTRL+F5.
Следует отметить, что использование заголовков запросов no-cache/no-store было, вероятно, плохим выбором при проектировании, так как ResponseCache ядра ASP.Net Core, скорее всего, будет использоваться сервером, который владеет ответом, а не промежуточным кэшем, таким как 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" предотвращал кэширование, если определенные условия запроса отличаются от ранее кэшированного запроса (например, пользовательский агент, accept-encoding и т. Д.). Наконец, если промежуточное программное обеспечение обрабатывает запрос, оно будет закорачивать позднее промежуточное программное обеспечение. Убедитесь, что ваше app.UseResponseCaching() зарегистрировано перед app.UseMVC()