Sdílet prostřednictvím


Zlepšení výkonu ukládáním výstupů do mezipaměti (C#)

od Microsoftu

V tomto kurzu se dozvíte, jak výrazně zlepšit výkon webových aplikací ASP.NET MVC tím, že využijete ukládání výstupu do mezipaměti. Dozvíte se, jak uložit výsledek vrácený z akce kontroleru do mezipaměti, aby se nemusel vytvářet stejný obsah pokaždé, když akci vyvolá nový uživatel.

Cílem tohoto kurzu je vysvětlit, jak můžete výrazně zlepšit výkon aplikace ASP.NET MVC tím, že využijete výstupní mezipaměť. Výstupní mezipaměť umožňuje ukládat obsah vrácený akcí kontroleru do mezipaměti. Díky tomu se nemusí generovat stejný obsah pokaždé, když se vyvolá stejná akce kontroleru.

Představte si například, že aplikace ASP.NET MVC zobrazí seznam databázových záznamů v zobrazení s názvem Index. Za normálních okolností pokaždé, když uživatel vyvolá akci kontroleru, která vrací zobrazení indexu, musí být sada databázových záznamů načtena z databáze provedením databázového dotazu.

Pokud na druhou stranu využijete výstupní mezipaměť, můžete se vyhnout spuštění databázového dotazu pokaždé, když jakýkoli uživatel vyvolá stejnou akci kontroleru. Zobrazení je možné načíst z mezipaměti namísto opětovného vygenerování z akce kontroleru. Ukládání do mezipaměti umožňuje vyhnout se provádění redundantní práce na serveru.

Povolení ukládání výstupu do mezipaměti

Ukládání výstupu do mezipaměti povolíte přidáním atributu [OutputCache] do jednotlivé akce kontroleru nebo celé třídy kontroleru. Například kontroler ve výpisu 1 zveřejňuje akci s názvem Index(). Výstup akce Index() se ukládá do mezipaměti po dobu 10 sekund.

Výpis 1 – Controllers\HomeController.cs

using System.Web.Mvc;

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

V beta verzích ASP.NET MVC nefunguje ukládání výstupu do mezipaměti pro adresu URL, jako je http://www.MySite.com/. Místo toho musíte zadat adresu URL, například http://www.MySite.com/Home/Index.

Ve výpisu 1 se výstup akce Index() ukládá do mezipaměti po dobu 10 sekund. Pokud chcete, můžete zadat mnohem delší dobu trvání mezipaměti. Pokud například chcete ukládat výstup akce kontroleru do mezipaměti po dobu jednoho dne, můžete zadat dobu trvání mezipaměti 86 400 sekund (60 sekund × 60 minut × 24 hodin).

Neexistuje žádná záruka, že obsah bude uložen v mezipaměti po dobu, kterou určíte. Když dojde k nedostatku paměťových prostředků, mezipaměť začne automaticky vyřadit obsah.

Kontroler Home ve výpisu 1 vrátí zobrazení indexu ve výpisu 2. Na tomto zobrazení není nic zvláštního. Zobrazení Index jednoduše zobrazuje aktuální čas (viz obrázek 1).

Výpis 2 – Views\Home\Index.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>

Obrázek 1 – Zobrazení indexu v mezipaměti

clip_image002

Pokud akci Index() vyvoláte několikrát zadáním adresy URL /Home/Index do adresního řádku prohlížeče a opakovaným stisknutím tlačítka Aktualizovat/Znovu načíst v prohlížeči, čas zobrazený v zobrazení Index se po dobu 10 sekund nezmění. Zobrazí se stejný čas, protože zobrazení je uložené v mezipaměti.

Je důležité si uvědomit, že pro každého, kdo navštíví vaši aplikaci, se ukládá stejné zobrazení do mezipaměti. Každý, kdo vyvolá akci Index(), získá stejnou verzi zobrazení Index v mezipaměti. To znamená, že množství práce, kterou webový server musí provést, aby obsloužil zobrazení indexu, je výrazně sníženo.

Zobrazení v seznamu 2 dělá něco opravdu jednoduchého. Zobrazení jenom zobrazuje aktuální čas. Stejně snadno byste ale mohli uložit do mezipaměti zobrazení, které zobrazuje sadu záznamů databáze. V takovém případě by se sada záznamů databáze nemusela načítat z databáze pokaždé, když se vyvolá akce kontroleru, která vrací zobrazení. Ukládání do mezipaměti může snížit množství práce, kterou musí webový i databázový server provést.

Nepoužívejte direktivu page <%@ OutputCache %> v zobrazení MVC. Tato direktiva už Web Forms světa krvácí a neměla by se používat v aplikaci ASP.NET MVC.

Kde se obsah ukládá do mezipaměti

Ve výchozím nastavení se při použití atributu [OutputCache] obsah ukládá do mezipaměti ve třech umístěních: na webovém serveru, na všech proxy serverech a ve webovém prohlížeči. Přesné umístění obsahu v mezipaměti můžete určit úpravou vlastnosti Location atributu [OutputCache].

Vlastnost Location (Umístění) můžete nastavit na některou z následujících hodnot:

· Libovolný

· Klienta

· Následný

· Server

· Žádný

· ServerAndClient

Ve výchozím nastavení má vlastnost Location hodnotu Any. Existují však situace, kdy můžete chtít ukládat do mezipaměti pouze v prohlížeči nebo pouze na serveru. Pokud například ukládáte do mezipaměti informace přizpůsobené jednotlivým uživatelům, neměli byste je ukládat do mezipaměti na serveru. Pokud zobrazujete různé informace různým uživatelům, měli byste je uložit do mezipaměti pouze v klientovi.

Například kontroler ve výpisu 3 zveřejňuje akci s názvem GetName(), která vrátí aktuální uživatelské jméno. Pokud se Jack přihlásí k webu a vyvolá akci GetName(), akce vrátí řetězec "Hi Jack". Pokud se následně Jill přihlásí k webu a vyvolá akci GetName(), získá také řetězec "Hi Jack". Řetězec se ukládá do mezipaměti na webovém serveru pro všechny uživatele po počátečním vyvolání akce kontroleru.

Výpis 3 – Controllers\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;
        }
    }
}

S největší pravděpodobností ovladač ve výpisu 3 nefunguje požadovaným způsobem. Nechcete zobrazovat zprávu "Hi Jack" pro Jill.

Personalizovaný obsah byste nikdy neměli ukládat do mezipaměti serveru. Můžete ale chtít přizpůsobený obsah uložit do mezipaměti prohlížeče, aby se zlepšil výkon. Pokud ukládáte obsah do mezipaměti v prohlížeči a uživatel několikrát vyvolá stejnou akci kontroleru, pak se obsah může načíst z mezipaměti prohlížeče místo ze serveru.

Upravený kontroler ve výpisu 4 ukládá výstup akce GetName() do mezipaměti. Obsah se však ukládá do mezipaměti pouze v prohlížeči a ne na serveru. Když pak metodu GetName() vyvolá více uživatelů, získá každý uživatel svoje vlastní uživatelské jméno a ne uživatelské jméno jiného uživatele.

Výpis 4 – Controllers\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;
        }
    }
}

Všimněte si, že atribut [OutputCache] ve výpisu 4 obsahuje vlastnost Location nastavenou na hodnotu OutputCacheLocation.Client. Atribut [OutputCache] obsahuje také vlastnost NoStore. Vlastnost Se používá k informování proxy serverů a prohlížeče, že by neměly ukládat trvalé kopie obsahu v mezipaměti.

Změna výstupní mezipaměti

V některých situacích můžete chtít různé verze stejného obsahu uložené v mezipaměti. Představte si například, že vytváříte stránku předlohy nebo podrobností. Na stránce předlohy se zobrazí seznam názvů filmů. Když kliknete na název, zobrazí se podrobnosti o vybraném filmu.

Pokud uložíte stránku podrobností do mezipaměti, zobrazí se podrobnosti pro stejný film bez ohledu na to, na který film kliknete. První film vybraný prvním uživatelem se zobrazí všem budoucím uživatelům.

Tento problém můžete vyřešit pomocí vlastnosti VaryByParam atributu [OutputCache]. Tato vlastnost umožňuje vytvořit různé verze stejného obsahu uložené v mezipaměti, pokud se liší parametr formuláře nebo parametr řetězce dotazu.

Například kontroler ve výpisu 5 zveřejňuje dvě akce s názvy Master() a Details(). Akce Master() vrátí seznam názvů filmů a akce Details() vrátí podrobnosti o vybraném filmu.

Výpis 5 – Controllers\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();
        }


    }
}

Akce Master() zahrnuje vlastnost VaryByParam s hodnotou none. Při vyvolání akce Master() se vrátí stejná verze hlavního zobrazení uložená v mezipaměti. Všechny parametry formuláře nebo parametry řetězce dotazu se ignorují (viz obrázek 2).

Obrázek 2 – zobrazení /Movies/Master

clip_image004

Obrázek 3 – zobrazení /Filmy/Podrobnosti

clip_image006

Akce Details() zahrnuje vlastnost VaryByParam s hodnotou Id. Když se akci kontroleru předají různé hodnoty parametru Id, vygenerují se různé verze zobrazení Podrobností uložené v mezipaměti.

Je důležité si uvědomit, že použití vlastnosti VaryByParam má za následek více ukládání do mezipaměti, a ne méně. Pro každou jinou verzi parametru Id se vytvoří jiná verze zobrazení Podrobností uložená v mezipaměti.

Vlastnost VaryByParam můžete nastavit na následující hodnoty:

* = Vytvořte jinou verzi uloženou v mezipaměti, kdykoli se liší parametr formuláře nebo řetězce dotazu.

none = Nikdy nevytvovávejte různé verze uložené v mezipaměti

Seznam parametrů středníkem = Vytvořit různé verze uložené v mezipaměti vždy, když se některý z parametrů formuláře nebo řetězce dotazu v seznamu liší.

Vytvoření profilu mezipaměti

Jako alternativu ke konfiguraci vlastností výstupní mezipaměti úpravou vlastností atributu [OutputCache] můžete vytvořit profil mezipaměti ve webovém konfiguračním souboru (web.config). Vytvoření profilu mezipaměti v konfiguračním souboru webu nabízí několik důležitých výhod.

Za prvé, když nakonfigurujete ukládání výstupu do mezipaměti v konfiguračním souboru webu, můžete řídit, jak akce kontroleru ukládají obsah do mezipaměti v jednom centrálním umístění. Můžete vytvořit jeden profil mezipaměti a použít ho na několik kontrolerů nebo akcí kontroleru.

Za druhé můžete upravit konfigurační soubor webu bez opětovného zkompilování aplikace. Pokud potřebujete zakázat ukládání do mezipaměti pro aplikaci, která už byla nasazena do produkčního prostředí, můžete jednoduše upravit profily mezipaměti definované v konfiguračním souboru webu. Všechny změny v konfiguračním souboru webu budou rozpoznány automaticky a použity.

Například <oddíl konfigurace webu ukládání do mezipaměti> v seznamu 6 definuje profil mezipaměti s názvem Cache1Hour. Oddíl <ukládání do mezipaměti> se musí zobrazit v oddílu <system.web> webového konfiguračního souboru.

Výpis 6 – Oddíl ukládání do mezipaměti pro web.config

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

Kontroler v výpisu 7 ukazuje, jak můžete použít profil Cache1Hour na akci kontroleru s atributem [OutputCache].

Výpis 7 – Controllers\ProfileController.cs

using System;
using System.Web.Mvc;

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

Pokud vyvoláte akci Index() vystavenou kontrolerem ve výpisu 7, vrátí se stejná doba po dobu 1 hodiny.

Souhrn

Ukládání výstupu do mezipaměti poskytuje velmi snadnou metodu výrazného zlepšení výkonu aplikací ASP.NET MVC. V tomto kurzu jste zjistili, jak použít atribut [OutputCache] k ukládání výstupu akcí kontroleru do mezipaměti. Také jste se dozvěděli, jak upravit vlastnosti atributu [OutputCache], jako jsou vlastnosti Duration a VaryByParam, aby se změnil způsob ukládání obsahu do mezipaměti. Nakonec jste se dozvěděli, jak definovat profily mezipaměti v konfiguračním souboru webu.