Een introductie rond Caching op het Azure Platform

Introductie

De drie grote blokken binnen het Azure platform bestaan weeral een tijdje. Misschien heb je zelf al een keer geëxperimenteerd met Windows Azure, SQL Azure of Azure AppFabric. De laatste in dat rijtje is dit jaar weer behoorlijk uitgebreid met nieuw en vooral interessante stukken die het hele Microsoft cloud gebeuren weer een stuk vollediger maken. In figuur 1 zien we een overzicht uit welke onderdelen Azure AppFabric momenteel bestaat.
 
Figuur 1: onderdelen van Azure AppFabric

Voordelen van caching

Snelheid en rationeel gebruik van de beschikbare hulpbronnen verbeteren voor je applicaties in de cloud. Dit zijn de troeven die caching je kunnen aanbieden.
 
Iedereen heeft momenteel de mond vol over rationeel gebruik van energie, een hulpbron die beperkt beschikbaar. Zo ook geldt dit voor een systeem als Azure waarbij er tijdens gebruik zoveel stress kan komen te liggen op beschikbare systemen dat er een flessenhalseffect optreedt. Vooral het aantal bevragingen naar SQL Azure, het database systeem, kan door middel van caching beperkt worden. Waarom telkens opnieuw die hele lijst met gemeenten of landen gaan ophalen? Het is nou niet zo dat die elke minuut veranderen. Een prima kandidaat om in cache te gaan steken.
 
Een verbetering in snelheid wordt bekomen door het feit dat de gegevens gemakkelijk aanspreekbaar zijn en ergens in een geheugen zitten dat snel uitgelezen kan worden. Je applicatie hoeft dus niet meer door alle lagen van je applicatie heen te fietsen, connectie leggen met een relatief trage data store en deze terug te geven.
 
Dat is best knap. Maar om nou ineens alles in cache te gaan steken is meestal ook niet zo een goed idee. Niet alle data is even geschikt om te cachen en aan het gebruik hangt ook een prijskaartje zoals we verder zullen zien. Weloverwogen keuzes en metingen zijn nodig om een goede balans te vinden.

Distributed caching

Zonder enige instelling zal caching standaard zich lokaal mee op de server waar de applicatie draait bevinden. Op een alleenstaande server vormt dat nauwelijks een probleem maar in een webfarm of een cloud omgeving kan dit soms onaangename verrassingen geven. Vooral bij het gebruik van sessions.
 
Een goede reden om over te gaan naar een cloud omgeving is omdat je snel wil kunnen schakelen indien je een plots hevig stijgende trafiek verwacht voor je applicatie. Je wilt dan zo veel mogelijk je applicatie draaiende houden en geen geheugen verspillen aan data in cache. Een ander probleem dat je uit de wereld wilt helpen is dat er misschien inconsistentie kan ontstaan tussen verschillende servers. Server A kan bijvoorbeeld nog oudere data in cache hebben staan dan Server B. Laat dat nou net relevante informatie zijn over prijzen van een duur horloge dat slechts om de week wordt aangepast. Net op het moment dat een koper dacht tegen een oude prijs het uurwerk te kopen blijkt dat er een prijswijziging is doorgevoerd met een verhoging van 100€. Bij afrekening wordt altijd de prijs genomen die in de databank komt te staan en je klant komt tot de vaststelling dat de prijs plots een pak hoger is. Zo een klant voelt zich terecht bekocht en zal de aankoop waarschijnlijk niet doorzetten.
 
Om dit op te lossen is distributed caching een oplossing. De cache, en dus de data, zit op een en dezelfde plaats beschikbaar en niet per server apart. Indien nodes terug opstarten, weggenomen worden of toegevoegd worden, al dan niet automatisch, blijft de cache toch altijd hetzelfde beschikbaar. Ook worden er geen overbodige hulpbronnen per server apart verbruikt.
 
AppFabric Caching maakt gebruik van het zogeheten cache-aside pattern. Dit houdt in dat wanneer de data niet beschikbaar is in cache, de applicatie zelf moet voorzien in de benodigde code om de originele data op te gaan halen en deze in cache te plaatsen.

Hoe integreren in je cloud applicatie?

Eens je een applicatie hebt gemaakt die op Windows Azure geplaatst kan worden, open je de portal (http://windows.azure.com). Je kiest in het menu voor Service Bus, Access Control & Caching. In het submenu erboven selecteer je Cache. Je komt dan terecht op het scherm zoals in figuur 2.
 
Figuur 2: Windows Azure portal
 
Vervolgens klik je op New in de ribbon. Daar vul je de gegevens in zoals in figuur 3. Let er wel op dat je even checkt of de namespace nog beschikbaar is mits deze uniek moet zijn.
 
Figuur 3: aanmaken van een nieuwe Cache namespace
 
Na deze aan te maken en even geduld uit te oefenen om deze aan te laten maken, druk je op View Client Configuration. Dit geeft je stukken xml terug welke je in je .config bestand moet toevoegen zoals in lijst 1. In het voorbeeld heb ik het securitytoken weggenomen voor de veiligheid maar deze wordt door de portal standaard voor jouw configuratie netjes ingevuld.
 
<configSections>
  <!-- Append below entry to configSections. Do not overwrite the full section. -->
  <section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere" />
</configSections>
<dataCacheClients>
  <dataCacheClient name="default">
    <hosts>
      <host name="SDNCache.cache.windows.net" cachePort="22233" />
    </hosts>
    <securityProperties mode="Message">
      <messageSecurity authorizationInfo="[token]"></messageSecurity>
    </securityProperties>
  </dataCacheClient>
</dataCacheClients>
Lijst 1: toevoegen van configuratie
 
Vergeet zeker niet in bovenstaande code het stuk [token] te vervangen door het token dat je vanuit de portal, eigen aan jouw omgeving, krijgt.
Om ook ASP.NET session state in te schakelen om met AppFabric Cache te werken hoeven we dit stukje xml extra toe te voegen aan de configuratie:
 
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">  <providers>    <add name="AppFabricCacheSessionStoreProvider"          type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"          cacheName="default"          useBlobMode="true"          dataCacheClientName="default" />  </providers>
</sessionState>







 

Let er wel op dat dit tussen <system.web> geplaatst wordt om foutmeldingen te voorkomen. De portal geeft dit ook netjes aan door voldoende commentaar toe te voegen aan de stukken die je dient te kopiëren.

 
Hierna dienen we nog enkele referenties toe te voegen aan ons project vanuit de Windows Appfabric SDK, namelijk:
 
#PNG KristvdMast04.png
 
Als je een fan bent van Nuget, en wie is dat niet, dan is er een heel handige package beschikbaar die het meeste van de configuratie aanbrengt en ook de benodigde referenties toevoegt aan je project. Met volgend commando vanuit de Package Manager Console krijg je de magie gewoon binnen voor een x64/.NET 4.0 configuratie:
 
Install-Package WindowsAzure.Caching
 
Nadien hoef je enkel de namespace en security token toe te voegen in het configuratiebestand en, indien gewenst, de stukken om session state en output caching ook mee in AppFabric caching te plaatsen.
 
Nu onze configuratie klaar staat hoeven we enkel code toe te voegen die gebruik gaat maken van het cache-aside pattern dat we hier hanteren.
 
    public class CityRepository
    {
        private static DataCacheFactory _cacheFactory = 

                           
new DataCacheFactory();
 
        public List<CityDTO> GetAllCities()
        {
            DataCache defaultCache = _cacheFactory.GetDefaultCache();
 
            // get it from cache
            List<CityDTO> cities = 
                         defaultCache.Get("cities") as List<CityDTO>;
            if (cities == null)
            {
                // from database when the cache didn't 
                // provide the data
                using (SDNEntities sdn = new SDNEntities())
                {
                    cities = (from c in sdn.Cities
                              orderby c.Name ascending 
                              select new CityDTO { ID = c.ID, 
                                     Name = c.Name })                        .ToList<CityDTO>();
                }
 
                // fill up cache
                defaultCache.Add("cities", cities, 
                                TimeSpan.FromMinutes(15));
            }
 
            return cities;
        }
    }
 
 
    public class CityDTO
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

 
 
In de functie GetAllCities nemen we eerst een referentie naar de default cache en op de lijn erna halen we de gemeenten, cities, uit de cache. Indien deze niet beschikbaar waren, zoals bij een eerste bevraging, worde deze uit de databank opgehaald. Hiervoor wordt Entity Framework gebruikt die connecteert met een SQL Azure databank. Deze data wordt dan in de cache zelf gestoken via:
 
defaultCache.Add("cities", cities, TimeSpan.FromMinutes(15));
 
We voorzien een timeout van 15 minuten vooraleer data terug opnieuw uit de databank moet komen om de cache op te vullen.

Local caching

Distributed caching is een prachtig mechanisme en het is al een pak sneller dan telkens opnieuw naar je databank te gaan. Echter mits het nog altijd ergens apart van je applicatie staat, is er toch nog een zekere vertraging om het op te halen. Voordien werd er gesteld dat je het liefst alle beschikbare hulpbronnen aan je applicatie laat maar stel dat je performantie vooropstelt kan je ook local caching aanzetten zodat de gegevens zowel in distributed cache, evenals lokaal, steken.
Deze functionaliteit aanzetten vereist weinig moeite en kan met volgende code in je configuratie toe te voegen in het dataCacheClient element:
 
  <localCache isEnabled="true"
           sync="TimeoutBased"
           objectCount="100000"
           ttlValue="300" />
 
Ietwat vreemd is de objectCount die effectief aanduidt hoeveel key-value paren je kan bijhouden in de local cache. Volgens dit voorbeeld kan je in local cache dus 100000 key-value paren bijhouden. Het attribuut ttlValue bepaald hoelang iets in local cache kan blijven zitten. In dit geval 300 seconden ofwel 5 minuten.
Maar wacht, als er nu cache lokaal staat en ergens anders, wat gebeurt er dan als die niet in de pas lopen? Klopt. En daarvoor zijn er dus enkele functies beschikbaar waarmee je dat kan afchecken en zo nodig de meest recente versie uit distributed cache kan halen.
 
DataCacheItemVersion version;DataCache cache = _cacheFactory.GetDefaultCache(); 
object cachedObject = cache.Get("item", out version);
 
if (version != null)
{
    object newerCachedObject = cache.GetIfNewer("item", ref version);
    if (newerCachedObject != null)
    {
        cachedObject = newerCachedObject;
    }
}


 

Dit stukje code laat zien dat een object uit cache wordt gehaald via de Get functie. Dit gebeurt enkel indien version, de out parameter, null is. Als er een nieuwere versie van het object in distributed cache steekt kan je die nadien met de functie GetIfNewer gaan ophalen.

 

Wat moet dat kosten?

Voor niets gaat de zon op. En daar blijft het meestal zowat bij. Zo ook in het geval van AppFabric Caching. Voor het gebruik worden volgende prijzen gehanteerd: 

Hoeveelheid
Kostprijs op maandbasis
128 Mb
$ 45
256 Mb
$ 55
512 Mb
$ 75
1 Gb
$ 110
2 Gb
$ 180
4 Gb
$ 325

De prijzen op zich zijn meestal vrij duidelijk bij het gebruik van het Azure platform maar niet altijd hoeveel je nodig hebt op voorhand. Mits er gebruik wordt gemaakt van het principe: betaal voor je wat gebruikt, is het aan te raden om wat hoger in te schatten dan wat je verwacht. Indien blijkt dat je applicatie ook met minder kan blijven werken, kan je via het portaal de waarde hiervan naar beneden stellen. Dat kan je op elk moment van de dag aanpassen, maar houdt er wel rekening mee dat deze aanpassing slechts een keer per dag zal doorgevoerd worden. Dus soms moet je gewoon wat geduld oefenen en voor maximaal een dag wat meer betalen voor je gemoedsrust.
 
Local caching extra gebruiken daarentegen is gewoon gratis. Dus een combinatie van zowel distributed als local caching kan voordelen bieden naar performantie toe zonder meerkost. Er komt gewoon wat extra code bij kijken.

Conclusie

In gemakkelijk en snel schaalbare webtoepassingen is een distributed caching verhaal een must. Microsoft heeft voor zijn Azure cloud platform eerder dit jaar een mooie oplossing aangeboden in de vorm van Azure AppFabric Caching. Het mooie aan het hele ecosysteem is dat het voor een programmeur heel gemakkelijk wordt gemaakt om het netjes te integreren in een applicatie.
 
Bij het in productie stellen van de applicatie wordt aangeraden om in het begin gewoon een hoog volume te gebruiken en het verbruik op te volgen en zo nodig naar een lager niveau bij te stellen om de kosten te drukken.

Links

Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar