"Först får det att fungera - sedan snabbt" är inte alltid rätt

Du kanske har hört programmeringsråden "Låt det först fungera - och sedan snabbt.". Det är inte helt fel. Utan rätt sammanhang brukar det emellertid feltolkas och inte tillämpas korrekt.

De bör hindra utvecklaren från att i förtid optimera kod, som kanske aldrig kommer att köras - eller så sällan körs, att en optimering inte skulle ha tillräcklig effekt för att motivera den insats som gjorts för optimeringen. Optimering kan dessutom leda till mer komplex kod och därmed medföra fel. Om du är utvecklare ska du alltså inte lägga alltför mycket tid på att mikrooptimera varje kodrad. Se bara till att du väljer rätt datastruktur, algoritmer och bibliotek och vänta på en profilerares hotspot-analys för att se var en mer detaljerad optimering kan öka den totala prestandan.

Arkitektbeslut och artefakter

Men råden"Först får det att fungera - sedan snabbt" är helt fel när det gäller"arkitektoniska" beslut. Vad är arkitektoniska beslut? Det vill säga: det är de beslut som är dyra, svåra och/eller omöjliga att ändra i efterhand. Tänk på att"dyr" ibland är detsamma som"omöjligt". När budgeten håller på att ta slut är det till exempel omöjligt att genomföra kostsamma ändringar. De största förändringarna inom infrastrukturen är förändringar inom denna kategori som de flesta kommer att tänka på. Men det finns också en annan typ av "arkitektoniska" artefakter som kan bli mycket otrevliga att förändra:

  1. Koddelar i ett programs"mitt", som många andra delar är beroende av. Om du ändrar dessa måste alla beroenden ändras och testas på nytt samtidigt.

  2. Artefakter, som ingår i vissa asynkrona, tidsberoende scenarier där indata - och därmed systemets beteende - kan variera mycket slumpmässigt. Ändringar kan ha oförutsägbara effekter och kan vara svåra att testa.

  3. Mönster som används och återanvänds om och om igen, i alla delar av systemet. Om programmönstret visar sig vara suboptimalt måste alla artefakter som använder mönstret kodas om.

Kommer du ihåg? På den här sidan sade vi att Dispatcher är en viktig del i ett AEM program. Åtkomsten till ett webbprogram är mycket slumpmässig - användarna kommer och kommer vid en oförutsägbar tidpunkt. Till slut kommer allt innehåll att (eller ska) cachas i Dispatcher. Om du har uppmärksammat detta kan du ha insett att cachning kan ses som en"arkitektur"-artefakt och därför bör förstås av alla teammedlemmar, utvecklare och administratörer.

Vi säger inte att en utvecklare faktiskt ska konfigurera Dispatcher. De måste känna till koncepten - särskilt gränserna - för att se till att deras kod också kan utnyttjas av Dispatcher.

Dispatcher förbättrar inte kodens hastighet på ett magiskt sätt. En utvecklare måste skapa sina komponenter med Dispatcher i åtanke. Därför måste han veta hur det fungerar.

Dispatcher Caching - grundläggande principer

Dispatcher som Http för cachelagring - belastningsutjämnare

Vad är Dispatcher och varför heter det "Dispatcher" i första hand?

Dispatcher är

  • Först och främst en cache

  • En omvänd proxy

  • En modul för Apache httpd-webbservern, som lägger till AEM funktioner till Apache-filens mångsidighet och smidigt fungerar tillsammans med alla andra Apache-moduler (som SSL eller SSI-inkluderingar som vi kommer att se senare)

I webbens tidiga dagar förväntar du dig ett par hundra besökare på en webbplats. En installation av en Dispatcher som"skickas" eller balanserar antalet förfrågningar till ett antal AEM publiceringsservrar och som vanligtvis var tillräckligt - dvs. namnet"Dispatcher". I dag används dock inte den här inställningen särskilt mycket längre.

Vi kommer att se olika sätt att konfigurera Dispatcher och Publish-system senare i den här artikeln. Först börjar vi med lite http-cachning-grunder.

Grundläggande funktioner i en Dispatcher-cache

Grundläggande funktioner i en Dispatcher-cache

Här förklaras grunderna i dispatchern. Dispatchern är en enkel cachelagring av omvänd proxy med möjlighet att ta emot och skapa HTTP-begäranden. En normal process för begäran/svar ser ut så här:

  1. En användare begär en sida
  2. Dispatcher kontrollerar om det redan finns en återgiven version av den sidan. Låt oss anta att det är den allra första begäran för den här sidan och att Dispatcher inte kan hitta en lokal cachelagrad kopia.
  3. Dispatcher begär sidan från Publish system
  4. På Publish återges sidan med en JSP- eller HTML-mall
  5. Sidan skickas tillbaka till Dispatcher
  6. Dispatcher cachelagrar sidan
  7. Dispatcher returnerar sidan till webbläsaren
  8. Om samma sida begärs en andra gång kan den hanteras direkt från Dispatcher-cachen utan att den behöver återges om på Publish-instansen. Detta sparar väntetid för användar- och processorcyklerna på Publish-instansen.

Vi pratade om "sidor" i sista delen. Men samma schema gäller även andra resurser som bilder, CSS-filer, PDF-nedladdningar och så vidare.

Hur data cachelagras

Dispatcher-modulen utnyttjar de funktioner som finns på Apache-värdservern. Resurser som HTML-sidor, nedladdningar och bilder lagras som enkla filer i Apache-filsystemet. Så enkelt är det.

Filnamnet härleds av URL:en för den begärda resursen. Om du begär en fil /foo/bar.html lagras den till exempel under /var/cache/docroot/foo/bar.html.

Om alla filer cachelagras och därmed lagras statiskt i Dispatcher kan du i princip dra Publish-systemets plug-in och Dispatcher fungerar som en enkel webbserver. Men detta är bara för att illustrera principen. Det verkliga livet är mer komplicerat. Du kan inte cachelagra allt och cachen är aldrig helt"full" eftersom antalet resurser kan vara oändligt på grund av återgivningsprocessens dynamiska karaktär. Modellen för ett statiskt filsystem hjälper till att generera en helhetsbild av avsändarens funktioner. Och det hjälper till att förklara begränsningarna med dispatchern.

AEM URL-struktur och filsystemsmappning

Om du vill ha mer information om Dispatcher kan du gå igenom strukturen för en enkel exempel-URL. Låt oss titta på exemplet nedan,

http://domain.com/path/to/resource/pagename.selectors.html/path/suffix.ext?parameter=value&otherparameter=value#fragment

  • http betecknar protokollet

  • domain.com är domännamnet

  • path/to/resource är sökvägen som resursen lagras i CRX och därefter i Apache-serverns filsystem

Härifrån skiljer det sig lite åt mellan AEM och Apache-filsystemet.

AEM

  • pagename är resursetiketten

  • selectors står för ett antal väljare som används i Sling för att bestämma hur resursen ska återges. En URL kan ha ett godtyckligt antal väljare. De avgränsas av en punkt. En väljarsektion kan till exempel vara "french.mobile.dit". Väljarna får endast innehålla bokstäver, siffror och bindestreck.

  • html som den sista av väljarna kallas för ett tillägg. I AEM/Sling avgör det också delvis återgivningsskriptet.

  • path/suffix.ext är ett sökvägsliknande uttryck som kan vara ett suffix till URL:en. Den kan användas i AEM skript för att ytterligare styra hur en resurs återges. Vi ska ha en hel sektion om den här delen senare. För tillfället bör det räcka att veta att du kan använda den som en extra parameter. Suffix måste ha ett tillägg.

  • ?parameter=value&otherparameter=value är frågeavsnittet i URL:en. Den används för att skicka godtyckliga parametrar till AEM. URL:er med parametrar kan inte cachelagras och parametrar bör därför begränsas till fall där de är absolut nödvändiga.

  • #fragment, fragmentdelen av en URL skickas inte till AEM den bara används i webbläsaren, antingen i JavaScript-ramverk som"routningsparametrar" eller för att hoppa till en viss del på sidan.

I Apache (refererar till bilden nedan),

  • pagename.selectors.html används som filnamn i cachens filsystem.

Om URL:en har suffixet path/suffix.ext,

  • pagename.selectors.html skapas som en mapp

  • path en mapp i mappen pagename.selectors.html

  • suffix.ext är en fil i mappen path. Obs! Om suffixet inte har något tillägg cachelagras inte filen.

Filsystemlayout efter hämtning av URL:er från Dispatcher

Filsystemlayout efter hämtning av URL:er från Dispatcher

Grundläggande begränsningar

Mappningen mellan en URL-adress, resursen och filnamnet är ganska enkel.

Du kanske har märkt några svällningar

  1. URL-adresser kan bli mycket långa. Om du lägger till sökvägsdelen av /docroot i det lokala filsystemet kan det vara enkelt att överskrida gränserna för vissa filsystem. Det kan vara svårt att köra Dispatcher i NTFS i Windows. Men du är säker med Linux.

  2. URL:er kan innehålla specialtecken och omljud. Detta är vanligtvis inget problem för dispatchern. Tänk dock på att URL-adressen tolkas på många ställen i programmet. Oftast har vi sett konstiga beteenden i ett program - bara för att ta reda på att en del sällan använd (anpassad) kod inte har testats noggrant för specialtecken. Du borde undvika dem om du kan. Och om du inte kan, planera för grundliga tester.

  3. I CRX har resurserna underresurser. En sida har t.ex. ett antal underordnade sidor. Detta kan inte matchas i ett filsystem eftersom filsystem har antingen filer eller mappar.

URL:er utan tillägg cachelagras inte

URL-adresser måste alltid ha ett tillägg. Även om du kan hantera URL:er utan tillägg i AEM. Dessa URL:er cachelagras inte i Dispatcher.

Exempel

http://domain.com/home.html är cacheable

http://domain.com/home är inte tillgänglig

Samma regel gäller när URL:en innehåller ett suffix. Suffixet måste ha ett tillägg för att kunna cachelagras.

Exempel

http://domain.com/home.html/path/suffix.html är cacheable

http://domain.com/home.html/path/suffix är inte tillgänglig

Du kanske undrar vad som händer om resursdelen inte har något tillägg, men suffixet har ett? I det här fallet har URL-adressen inget suffix alls. Titta på nästa exempel:

Exempel

http://domain.com/home/path/suffix.ext

/home/path/suffix är sökvägen till resursen… så det finns inget suffix i URL:en.

Slutsats

Lägg alltid till tillägg till både sökvägen och suffixet. SEO-medvetna personer hävdar ibland att detta rankar dig i sökresultaten. Men en sida som inte är cachelagrad skulle bli mycket långsam och rankas ännu längre.

Suffix-URL i konflikt

Du kan ha två giltiga URL:er

http://domain.com/home.html

och

http://domain.com/home.html/suffix.html

De är helt giltiga i AEM. Du skulle inte se några problem på din lokala utvecklingsmaskin (utan Dispatcher). Troligen kommer du inte heller att stöta på några problem med UAT- eller inläsningstestning. Det problem vi står inför är så subtilt att det glider igenom de flesta tester. Den kommer att drabba dig hårt när du är i toppläge och du har begränsad tid att ta itu med den, troligen inte har någon serveråtkomst eller resurser att åtgärda den. Vi har varit där…

Så… vad är problemet?

home.html i ett filsystem kan vara en fil eller en mapp. Inte båda samtidigt som i AEM.

Om du begär home.html först skapas den som en fil.

Efterföljande begäranden till home.html/suffix.html returnerar giltiga resultat, men eftersom filen home.html"blockerar" positionen i filsystemet kan home.html inte skapas en andra gång som en mapp och home.html/suffix.html därför inte cachelagras.

Filblockeringspositionen i filsystemet förhindrar att underresurser cachas

Filblockeringspositionen i filsystemet förhindrar att underresurser cachas

Om du gör det tvärtom, begär först home.html/suffix.html, cachelagras suffix.html under en mapp /home.html först. Den här mappen tas dock bort och ersätts av filen home.html när du efterfrågar home.html som en resurs.

Tar bort en sökvägsstruktur när en överordnad hämtas som en resurs

Tar bort en sökvägsstruktur när en överordnad hämtas som en resurs

Resultatet av det som cachelagras är alltså helt slumpmässigt och beroende på ordningen för inkommande begäranden. Det som gör det ännu svårare är det faktum att du vanligtvis har mer än en dispatcher. Och prestanda, cache-träfffrekvens och -beteende kan variera från en Dispatcher till en annan. Om du vill ta reda på varför din webbplats inte svarar måste du se till att du tittar på rätt Dispatcher med den olyckliga cachningsordningen. Om du tittar på Dispatcher som - av tur - hade ett mer fördelaktigt mönster för förfrågningar, kommer du att gå vilse när du försöker hitta problemet.

Undvika URL-konflikter

Du kan undvika"URL-konflikter", där ett mappnamn och ett filnamn"konkurrerar" om samma sökväg i filsystemet, när du använder ett annat tillägg för resursen när du har ett suffix.

Exempel

  • http://domain.com/home.html

  • http://domain.com/home.dir/suffix.html

Båda är helt lättåtkomliga.

Välj en dedikerad dir för ett tillägg för en resurs när du begär ett suffix eller så undviker du att använda suffixet helt och hållet. Det finns sällsynta fall där de är användbara. Och det är enkelt att implementera dessa fall korrekt. Som vi kommer att se i nästa kapitel när vi talar om cache-ogiltigförklaring och tömning.

Otillgängliga begäranden

Låt oss titta på en kort sammanfattning av det sista kapitlet plus några andra undantag. Dispatcher kan cachelagra en URL om den är konfigurerad som cacheable och om det är en GET-begäran. Den kan inte cachas med något av följande undantag.

Cacheable-begäranden

  • Begäran är konfigurerad att vara tillgänglig i Dispatcher-konfigurationen
  • Begäran är en ren GET-begäran

Begäranden eller svar som inte kan cachelagras

  • Begäran som nekas cachelagring av konfiguration (sökväg, mönster, MIME-typ)
  • Svar som returnerar rubriken"Dispatcher: no-cache"
  • Svar som returnerar huvudet Cache-Control: no-cache|private
  • Svar som returnerar rubriken "Pragma: no-cache"
  • Begäran med frågeparametrar
  • URL utan tillägg
  • URL med ett suffix som inte har något tillägg
  • Svar som returnerar en annan statuskod än 200
  • Begäran om POST