Cachování v aplikacích ASP.NET

7. května 2003

Systém ASP.NET disponuje komplexním mechanismem cachování jakéhokoli objektu, a to volitelně kdekoli „po trase“ od vystavení dat v paměti serveru až po prohlížeč klienta. S jeho využitím můžeme dramaticky zvýšit výkon webových aplikací.

Cachování objektů na úrovni aplikaci obstarává instance třídy System.Web.Caching.Cache, můžeme tedy mít v různých aplikacích nezávisle na sobě cachované objekty se stejným klíčem (názvem). Komplexnost cachování doplňují další třídy, jako například System.Web.HttpCachePolicy. Společně pak díky těmto třídám můžeme:

  • vložit do cache jakýkoli objekt
  • určit, jak dlouho má v objekt v cachi zůstat (duration)
  • definovat závislost mezi cachovaným objektem a jiným (i) cachovaným objektem nebo závislost na souboru nebo adresáři (cache dependency)
  • určit, kde se objekt nebo data objektu po trase ke klientovi mají cachovat (location)
  • vynutit zákaz cachování

V tomto článku si probereme základní možnosti použití – cachování výsledků celé stránky a rozdílné nastavení cachování pro použité uživatelské ovládací prvky. Nejjednodušší použití je zapnutí cachování pomocí direktivy OutputCache ve stránce:

<%@ OutputCache Duration=“sekundy“ Location=“Any | Client | Downstream | Server | None“ Shared=“True | False“ VaryByControl=“controlname“ VaryByCustom=“browser | customstring“ VaryByHeader=“headers“ VaryByParam=“parametername“ %>

Direktiva má několik atributů, některé jsou určeny pro použití ve stránce, některé pouze pro použití v ovládacím prvku (již z toho je možné usoudit, že ovládací prvky mohou být cachovány zcela jinak než zbytek stránky). Než si atributy popíšeme, podívejme se na triviální ukázku – do stránky budeme vypisovat aktuálně zjištěný čas. Pokud by se takováto stránka necachovala, při každém reloadu stránky se nám objeví aktuální čas. Pokud nastavíme, aby se stránka cachovala po dobu 15 sekund, pak po prvním nacachování, kdy se ukáže aktuální čas, bude v průběhu dalších 15 sekund při každém reloadu stránka předávána z cache a tak bude na stránce zobrazen stále stejný čas. Jakmile vyprší čas povoleného cachování, stránka se vystaví celá znovu a zobrazovaný čas se změní.

<%@ Page Language=“C#“ %>
<%@ OutputCache Duration=“15″ VaryByParam=“None“ %>
<script language=“C#“ runat=“server“>
void Page_Load(object sender, EventArgs e)
{
  myLabel.Text=DateTime.Now.ToString();
}
</script>
<html>
<body>
  <asp:label id=“myLabel“ runat=“server“ />
</body>
</html>

Jak vidíme z ukázky, začít využívat cache je velmi jednoduché a v podstatě spíše není důvod cache nevyužívat, vyjma aplikací, které musí zobrazovat aktuální data (různá online administrační rozhraní pro editaci údajů v databázi a podobně). Je dobré si uvědomit, že v extrémní zátěži má smysl cachovat třeba i jen 2 sekundy – pokud je velký nápor požadavků, část jich bude, místo vytahování údajů ze zdroje dat (databáze, XML soubor, webová služba), obsloužena pomocí cache. I když je samozřejmě vhodné využívat dobu cachování podle možností co nejdelší.

Následuje popis atributů direktivy OutputCache:

Duration Čas v sekundách, po který bude stránka nebo uživatelský prvek cachován, nastavením tohoto atributu se zavádí tzv. expiration policy pro odpovědi na HTTP požadavky – hlavičky jsou jsou doplněny o potřebné údaje. Tento atribut je povinný, musí být uveden.
Location Určuje, kde se má nebo může objekt cachovat (OutputCacheLocation), výchozí je Any. Není podporován pro uživatelské prvky (*.ascx).

  • Any – data objektu mohou být a budou cachována kdekoli je to možné (v prohlížeči klienta, na proxy serveru nebo jiném serveru, který se podílí na vyřizování požadavku, nebo na serveru, který vyřizuje požadavek)
  • Client – cachovat v browseru klienta
  • Downstream – kdekoli kromě serveru, který obsluhuje požadavek (tedy v prohlížeči, na proxy nebo jinde „po trase“)
  • Server – pouze na web serveru
  • None – vynutí vypnutí (potlačení) cachování
Shared Pouze pro uživatelské ovládací prvky, určuje, zda prvek použitý ve více stránkách může být sdílen v cache, výchozí hodnota je false. Pokud nastavíme true, pak bude jedna verze prvku v cache použita pro všechny stránky, které tento prvek obsahují. Pokud používáte takové prvky, které mají vždy stejný obsah nezávisle na čemkoli, je velmi vhodné pro úsporu paměti povolit jejich sdílení, viz cachování částí ASP.NET stránky.
VaryByParam Středníky oddělený seznam parametrů, na kterých má záviset cachování. Výchozí nastavení je takové, že nastavení odpovídá parametrům předaným aplikaci metodou GET nebo POST. Pokud je uvedeno více parametrů, pak se do cache ukládá objekt pro každý požadavek s rozdílnou hodnotou zvoleného parametru zvlášť. Možné je použít také none (na hodnoty parametrů není brán zřetel) nebo *, kdy se bude cachovat odděleně v závislosti na všech předávaných parametrech. Atribut je povinný pro stránku (*.aspx) a pro uživatelský prvek, pokud současně neobsahuje VaryByControl atribut.
VaryByControl Středníky oddělený seznam řetězců použitých pro řízení cachování uživatelského ovládacího prvku (*.ascx), tyto řetězce reprezentují hodnotu ID vlastnosti ASP.NET serverových ovládacích prvků, které jsou v tomto našem uživatelském prvku použity, viz cachování částí ASP.NET stránky. Atribut není určen pro použití ve stránce (*.aspx), naopak musí být uveden v ovládacím prvku, pokud není uveden atribut VaryByParam.
VaryByCustom Libovolný text (řetězec) reprezentující požadavek na cachování, pokud je nastavena hodnota browser, cache je řízena v závislosti na jménu a major verzi předávaných prohlížečem klienta. Pokud je zadán uživatelský řetězec, je potřeba předefinovat (napsat vlastní) metodu HttpApplication.GetVaryByCustomString v souboru Global.asax.
VaryByHeader Středníky oddělený seznam HTTP hlaviček, které mají ovlivňovat uložení objektu do cache. Pokud je uvedeno více hlaviček, cache bude obsahovat podle každého specifického požadavku s rozdílnými hlavičkami jinou verzi. Při nastavení tohoto atributu je využíváno cachování dle HTTP 1.1 všude, kde to lze, z toho také vyplývá, že není podporován v uživatelských ovládacích prvcích. Možné hodnoty:

  • Accept
  • Accept-Charset
  • Accept-Encoding
  • Accept-Language
  • Authorization
  • Content-Encoding
  • Expect
  • From
  • Host
  • If-Match
  • If-Modified-Since
  • If-None-Match
  • If-Range
  • If-Unmodified-Since
  • Max-Forwards
  • Proxy-Authorization
  • Range
  • Referer
  • TE
  • User-Agent

V některých případech jsou ještě zvlášť modifikovány HTTP hlavičky, například pokud webový formulář vyžaduje autorizaci uživatele, Cache-Control hlavička je nastavena na private (viz cachování ASP.NET stránek).

Ještě dva příklady. První pro cachování po dobu jedné hodiny v závislosti na parametru id a start – pokud budou předávány nějaké další parametry, nebudou mít vliv na již nacachovaný objekt v cache. Druhý příklad zapne cachování na jednu minutu v závislosti na refereru a kódování obsažené v HTTP hlavičkách při komunikaci.

<%@ OutputCache Duration=“3600″ VaryByParam=“id ;start “ %>
<%@ OutputCache Duration=”60” VaryByHeader=”Referer;Content-Encoding” %>

Nastavení direktivy OutputCache je totéž, jakobychom programově nastavovali vlastnosti HttpCachePolicy.SetExpires a HttpCachePolicy.SetCacheability metod prostřednictvím HttpResponse.Cache. Zde si proto můžeme zjednodušeně ukázat, jak manipulovat s cachováním programově.

<%@ OutputCache Duration=“60″ VaryByParam=“None“ %>
// nebo
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);

<%@ OutputCache Duration=“60″ Location=“Client“ VaryByParam=“None“ %>
// nebo
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Private);

<%@ OutputCache Duration=“60″ Location=“Downstream“ VaryByParam=“None“ %> // nebo Response.Cache.SetExpires(DateTime.Now.AddSeconds(60)); Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetNoServerCaching();

<%@ OutputCache Duration=“60″ Location=“Server“ VaryByParam=“None“ %> // nebo Response.Cache.SetExpires(DateTime.Now.AddSeconds(60)); Response.Cache.SetCacheability(HttpCacheability.Server);

<%@ OutputCache duration=“60″ varybyparam=“Interval“ %> // nebo Response.Cache.SetExpires(DateTime.Now.AddSeconds(60)); Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.VaryByParams[„Interval“] = true;

<%@ OutputCache Location=“None“ VaryByParam=“None“ %>
// nebo
Response.Cache.SetCacheability(HttpCacheability.NoCache); // vypne cache všude (na serveru, u klienta i jinde po trase)

Jak vidíme, použití direktivy OutputCache je opravdu snadné a pokud se nechystáme vytvářet speciální aplikace, s jejím použitím není problém. Touto direktivou se modifikují také HTTP hlavičky a de facto můžeme říci, že je z naší stránky cachováno vše, co do browseru vypadne jako kód nějakého prvku nebo výstup metody Response.Write. Pokud však používáme jiný výstup (například generování obrázku), tuto jednoduchou metodu nemůžeme použít, nebude pracovat správně. V těchto případech si cachování musíme ošetřit programově sami, což si ukážeme v některém dalším článku.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *