úterý 6. října 2015

Poznámky z Code Review - kešování pro jednotlivé jazyky

Kešování hotových stránek či v případě MVC výsledků view je jedním z mnoha způsobů, jak zvýšit výkon aplikace. Samozřejmě nic není zadarmo a v případě kešování se platí spotřebovanou pamětí. Ale i u kešování mohou nastat na první pohled zanedbatelné problémy, obzvláště v případě, že kešováný obsah je nějakým způsobem závislý například na nastaveném jazyku či kultuře volajícího.

V jednom ASP.NET MVC projektu bylo použito partial view volané přes akci z několika dalších view, tedy typicky view obsahovalo toto volání:

@{ Html.RenderAction("JsStaticResources", "Service");

a následně v kontroleru pak bylo jen vrácení částečného view:

public ActionResult JsStaticResources()
{
    return PartialView("_JsStaticResources");
}

V partial view se rendrovali hlavně různé hlášení a javascriptový kód. Protože je projekt vícejazyčný, hlášky se načítali z resource souborů.

Při analýze výkonu se zjistilo, že zrenderování tohoto partial view trvá poměrně dlouho - a tak byl přidán atribut OutputCache a výkonově se zdálo vše v pořádku.

[OutputCache(Duration = 600)]
public ActionResult JsStaticResources()
{
    return PartialView("_JsStaticResources");
}

Aplikace je používaná zejména v anglicky mluvících zemích a tedy i testování je prováděno většinou s ohledem na tuto skutečnost. A tak se přehlédlo, že čínský uživatel může najednou vidět anglická hlášení a nebo - což by byl horší případ -  pokud prvním uživatelm po spuštění aplikace byl člověk, jehož rodným jazykem je čínština, tak by ostatní uživatelé viděli hlášení v čínštině.

Vypadalo to nějak takto:


Přitom náprava je jednoduchá, je nutné jen kešovat v závislosti na jazyce. Do souboru global.asax se doplní následující metoda (respektive se přepíše):

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    if (string.Compare(custom, "UICulture") == 0)  
    {
        string cultureName = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
        return cultureName;
    }

    return base.GetVaryByCustomString(context, custom);
}

A deklarace atributu u příslušené akční metody, jejíž výstup chceme podmíněně kešovat se upraví takto přiřazením hodnoty k parametru VaryBuCustom:

[OutputCache(Duration = 600, VaryByCustom="UICulture")]
public ActionResult JsStaticResources()
{
    return PartialView("_JsStaticResources");
}

A hned vše funguje jak má:



Při používání  kešování je nutné být opatrný v tom, aby počet kešovaných instancí nepřesáhl rozumný počet, respektive aby samotné kešování neztratilo význam například vzhledem k tomu, kolik paměti spotřebuje. 

Žádné komentáře:

Okomentovat