Повышение производительности благодаря кэшированию вывода (C#)

корпорацией Майкрософт

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

Цель этого руководства состоит в том, чтобы объяснить, как вы можете значительно улучшить производительность приложения mVC ASP.NET, воспользовавшись выходным кэшем. Выводной кэш позволяет кэшировать содержимое, возвращенное действием контроллера. Таким образом, одно и то же содержимое не должно создаваться каждый раз, когда вызывается одно и то же действие контроллера.

Представьте себе, например, что ваше приложение mVC ASP.NET отображает список записей баз данных в представлении под названием Index. Обычно каждый раз, когда пользователь вызывает действие контроллера, возвращающего представление Индекса, набор записей базы данных должен быть извлечен из базы данных путем выполнения запроса базы данных.

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

Включение кэшинга выходов

Вы позволяете кэшировать выход, добавляя атрибут «OutputCache» либо к индивидуальному действию контроллера, либо к всему классу контроллера. Например, контроллер в листинге 1 предоставляет действие под названием Индекс(). Выход действия Индекса () кэшируется в течение 10 секунд.

Список 1 - Контролеры-HomeController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        [OutputCache(Duration=10, VaryByParam="none")]
        public ActionResult Index()
        {
            return View();
        }
    }
}

В бета-версиях ASP.NET MVC кэширование вывода не http://www.MySite.com/работает для URL-адреса. Вместо этого необходимо ввести http://www.MySite.com/Home/IndexURL-адрес типа.

В листинге 1 выход действия Индекса () кэшируется в течение 10 секунд. Если вы предпочитаете, вы можете указать гораздо более длительную продолжительность кэша. Например, если вы хотите кэшировать выход действия контроллера в течение одного дня, то можно указать * продолжительность * кэша 86400 секунд (60 секунд 60 минут 24 часа).

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

Домашний контроллер в листинге 1 возвращает представление индекса в листинге 2. В этом представлении нет ничего особенного. Представление индекса просто отображает текущее время (см. рисунок 1).

Список 2 - Просмотры »Домашний»Индекс.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    
    The current time is: <%= DateTime.Now.ToString("T") %>
    
    
    </div>
</body>
</html>

Рисунок 1 - Представление кэшированного индекса

clip_image002

Если вы ссылаетесь на действие Index() несколько раз, введя URL/Home/Index в адресной строке браузера и нажав кнопку Refresh/Reload в браузере повторно, то время, отображаемые представлением Индекса, не изменится в течение 10 секунд. То же время отображается, потому что представление кэшировано.

Важно понимать, что одно и то же представление кэшируется для всех, кто посещает ваше заявление. Любой, кто вызывает действие Index() получит ту же кэшированную версию представления Индекса. Это означает, что объем работы, которую веб-сервер должен выполнять для обслуживания представления Индекса, резко сокращается.

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

Не используйте <> страницу в представлении MVC % % Эта директива истекает из мира Web Forms и не должна использоваться в ASP.NET приложении MVC.

Где кэшируется содержимое

По умолчанию при использовании атрибута «OutputCache» содержимое кэшируется в трех местах: веб-сервере, любых прокси-серверах и веб-браузере. Вы можете точно управлять местом кэширования содержимого, изменяя свойство местоположения атрибута «OutputCache».

Вы можете установить свойство Место для любого из следующих значений:

· Любой

· Клиента

· Вниз по течению

· Сервера

· Ни один

· Сервериклиент

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

Например, контроллер в листинге 3 предоставляет действие под названием GetName(), которое возвращает текущее имя пользователя. Если Джек входит в веб-сайт и вызывает действие GetName() затем действие возвращает строку "Привет Джек". Если впоследствии Джилл входит в веб-сайт и вызывает действие GetName() затем она также получит строку "Привет Джек". Строка кэшируется на веб-сервере для всех пользователей после того, как Джек первоначально вызывает действие контроллера.

Список 3 - Контролеры-BadUserController.cs

using System.Web.Mvc;
using System.Web.UI;

namespace MvcApplication1.Controllers
{
    public class BadUserController : Controller
    {
        [OutputCache(Duration = 3600, VaryByParam = "none")]
        public string GetName()
        {
            return "Hi " + User.Identity.Name;
        }
    }
}

Скорее всего, контроллер в листинге 3 работает не так, как вы хотите. Вы не хотите, чтобы отобразить сообщение "Привет Джек" Джилл.

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

Модифицированный контроллер в листинге 4 кисти выход действия GetName() . Однако содержимое кэшируется только на браузере, а не на сервере. Таким образом, когда несколько пользователей ссылаться на метод GetName() каждый человек получает свое собственное имя пользователя, а не имя пользователя другого человека.

Список 4 - Контроллеры/UserController.cs

using System.Web.Mvc;
using System.Web.UI;

namespace MvcApplication1.Controllers
{
    public class UserController : Controller
    {
        [OutputCache(Duration=3600, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]
        public string GetName()
        {
            return "Hi " + User.Identity.Name;
        }
    }
}

Обратите внимание, что атрибут «OutputCache» в листинге 4 включает свойство местоположения, установленное значение outputCacheLocation.Client. Атрибут «OutputCache» также включает свойство NoStore. Свойство NoStore используется для информирования прокси-серверов и браузера о том, что они не должны хранить постоянную копию кэшированного содержимого.

Изменение кэша выходов

В некоторых ситуациях может потребоваться различные кэшированные версии одного и того же содержимого. Представьте себе, например, что вы создаете страницу master/detail. На главной странице отображается список названий фильмов. При нажатии на заголовок вы получаете подробную информацию для выбранного фильма.

Если вы кэшируете страницу деталей, то детали для того же фильма будут отображаться независимо от того, какой фильм вы нажмете. Первый фильм, выбранный первым пользователем, будет отображаться всем будущим пользователям.

Эту проблему можно решить, воспользовавшись свойством VaryByParam атрибута «OutputCache». Это свойство позволяет создавать различные кэшированные версии одного и того же содержимого при различном параметре строки формы или строке запроса.

Например, контроллер в листинге 5 предоставляет два действия под названием Master() и Детали (). Действие Master() возвращает список названий фильмов, а действие «Подробности» () возвращает детали выбранного фильма.

Список 5 - Контролеры-MoviesController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class MoviesController : Controller
    {
        private MovieDataContext _dataContext;

        public MoviesController()
        {
            _dataContext = new MovieDataContext();
        }

        [OutputCache(Duration=int.MaxValue, VaryByParam="none")]
        public ActionResult Master()
        {
            ViewData.Model = (from m in _dataContext.Movies 
                              select m).ToList();
            return View();
        }

        [OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
        public ActionResult Details(int id)
        {
            ViewData.Model = _dataContext.Movies.SingleOrDefault(m => m.Id == id);
            return View();
        }


    }
}

Действие Master() включает свойство VaryByParam со значением "нет". При вызове действия Master() возвращается та же кэшированная версия представления Master. Любые параметры формы или параметры строки запроса игнорируются (см. рисунок 2).

Рисунок 2 - Просмотр /Фильмов/Мастер

clip_image004

Рисунок 3 - Просмотр /Фильмов/Подробности

clip_image006

Детали () действие включает в себя свойство VaryByParam со значением "Id". Когда различные значения параметра Id передаются в действие контроллера, генерируются различные кэшированные версии представления Детали.

Важно понимать, что использование свойства VaryByParam приводит к большему кэшированию и не меньшему. Для каждой другой версии параметра Id создается другая кэшированная версия представления «Детали».

Свойство VaryByParam можно установить на следующие значения:

*Создайте другую кэшированную версию всякий раз, когда параметр строки формы или строки запроса изменяется.

ни когда не создавайте различные кэшированные версии

Список параметров Semicolon - Создание различных кэшированных версий всякий раз, когда какие-либо параметры строки формы или строки запроса в списке различаются

Создание профиля кэша

В качестве альтернативы настройке свойств кэша вывода путем изменения свойств атрибута «OutputCache» можно создать профиль кэша в веб-конфигурации (web..config). Создание профиля кэша в файле конфигурации веб-страниц дает несколько важных преимуществ.

Во-первых, нанастройки кэширования вывода в файле конфигурации веб-страниц можно контролировать, как контроллер действия кэша содержание в одном центральном месте. Можно создать один профиль кэша и применить профиль к нескольким контроллерам или действиям контроллера.

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

Например, <раздел> конфигурации кэширования в листинге 6 определяет профиль кэша под названием Cache1Hour. Раздел <кэширования> должен <отображаться> в разделе system.web файла конфигурации паутины.

Список 6 - Кэшинг раздел для web.config

<caching>
<outputCacheSettings>
    <outputCacheProfiles>
        <add name="Cache1Hour" duration="3600" varyByParam="none"/>
    </outputCacheProfiles>
</outputCacheSettings>
</caching>

Контроллер в листинге 7 иллюстрирует, как можно применить профиль Cache1Hour к действию контроллера с атрибутом «OutputCache».

Список 7 - Контролеры

using System;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class ProfileController : Controller
    {
        [OutputCache(CacheProfile="Cache1Hour")]
        public string Index()
        {
            return DateTime.Now.ToString("T");
        }
    }
}

Если вы вызываете действие Index(), выставленное контроллером в листинге 7, то то же время будет возвращено в течение 1 часа.

Сводка

Кэширование на выходе обеспечивает вам очень простой метод резкого повышения производительности ASP.NET mVC-приложений. В этом уроке вы узнали, как использовать атрибут «OutputCache» для кэша вывода действий контроллера. Вы также узнали, как изменять свойства атрибута «OutputCache», такие как Свойства Продолжительность и VaryByParam, чтобы изменить способ кэши. Наконец, вы узнали, как определить профили кэша в файле конфигурации веб-страниц.