"Prima fare funzionare - poi rendere veloce" Non è sempre giusto

È possibile che si sia sentito il consiglio di programmazione "Prima renderlo operativo, quindi renderlo veloce.". Non è del tutto sbagliato. Tuttavia, senza il contesto giusto, tende a essere male interpretata e non applicata correttamente.

Il consiglio dovrebbe evitare che lo sviluppatore ottimizzi anticipatamente il codice, che potrebbe non essere mai eseguito - o che viene eseguito così raramente, che un’ottimizzazione non avrebbe un impatto sufficiente per giustificare lo sforzo inserito nell’ottimizzazione. Inoltre, l’ottimizzazione potrebbe portare a codice più complesso e quindi introdurre bug. Quindi, se sei uno sviluppatore, non spendere troppo tempo sulla micro-ottimizzazione di ogni singola riga di codice. Assicurati di scegliere le strutture di dati, gli algoritmi e le librerie giuste e attendi l’analisi dei punti attivi di un profiler per vedere dove un’ottimizzazione più approfondita potrebbe aumentare le prestazioni complessive.

Decisioni di architettura e artefatti

Tuttavia, il consiglio di "prima farlo funzionare - poi farlo in fretta" è completamente sbagliato quando si tratta di decisioni "architettoniche". Cosa sono le decisioni architettoniche? In poche parole, sono decisioni costose, difficili e/o impossibili da cambiare in seguito. Tieni presente che "costoso" a volte equivale a "impossibile". Ad esempio, quando il progetto sta esaurendo il budget, è impossibile implementare costose modifiche. I cambiamenti infrastrutturali sono il primo tipo di cambiamenti in quella categoria che viene nella mente della maggior parte delle persone. Ma c'è anche un altro tipo di artefatti "architettonici" che possono diventare molto negativi da cambiare:

  1. Pezzi di codice nel "centro" di un’applicazione, su cui si basano molti altri pezzi. La modifica di queste, richiede che tutte le dipendenze vengano modificate e testate di nuovo contemporaneamente.

  2. Gli artefatti, che sono coinvolti in alcuni scenari asincroni, dipendenti dal tempo in cui l'input - e quindi il comportamento del sistema può variare in modo molto casuale. I cambiamenti possono avere effetti imprevedibili e possono essere difficili da testare.

  3. Modelli di software che vengono utilizzati e riutilizzati più e più volte, in tutte le parti del sistema. Se il modello software risulta non ottimale, tutti gli artefatti che utilizzano il modello devono essere codificati nuovamente.

Ricordi? In cima a questa pagina abbiamo detto che il Dispatcher è una parte essenziale di un'applicazione AEM. L’accesso a un’applicazione web è molto casuale: gli utenti arrivano e partono in momenti imprevedibili. Alla fine, tutti i contenuti saranno (o dovrebbero) memorizzati nella cache di Dispatcher. Quindi, se presti molta attenzione, potresti aver capito che la memorizzazione in cache potrebbe essere vista come un artefatto "architetturale" e quindi dovrebbe essere compresa da tutti i membri del team, sviluppatori e amministratori allo stesso modo.

Non stiamo dicendo che uno sviluppatore debba effettivamente configurare Dispatcher. Devono conoscere i concetti, in particolare i confini, per assicurarsi che il loro codice possa essere utilizzato anche da Dispatcher.

Il Dispatcher non migliora magicamente la velocità del codice. Uno sviluppatore deve creare i suoi componenti pensando a Dispatcher. Pertanto, ha bisogno di sapere come funziona.

Memorizzazione in cache di Dispatcher - Principi di base

Dispatcher as Caching Http - Bilanciatore del carico

Che cos'è Dispatcher e perché si chiama "Dispatcher"?

Il Dispatcher è

  • Prima di tutto una cache

  • Un proxy inverso

  • Un modulo per il server web Apache httpd, che aggiunge funzionalità relative all’AEM alla versatilità di Apache e funziona senza problemi insieme a tutti gli altri moduli Apache (come SSL o anche SSI include come vedremo in seguito)

Nei primi giorni del web, ci si aspetta qualche centinaio di visitatori di un sito. La configurazione di un Dispatcher, "inviato" o bilanciava il carico di richieste a diversi server di pubblicazione AEM e che di solito era sufficiente, quindi il nome "Dispatcher". Al giorno d’oggi, tuttavia, questa configurazione non viene più utilizzata molto frequentemente.

Vedremo diversi modi per configurare i sistemi Dispatcher e Publish più avanti in questo articolo. Iniziamo con alcune nozioni di base sulla memorizzazione in cache http.

Funzionalità di base di una cache di Dispatcher

Funzionalità di base di una cache di Dispatcher

Le nozioni di base del dispatcher sono illustrate qui. Dispatcher è un proxy inverso di memorizzazione nella cache semplice che consente di ricevere e creare richieste HTTP. Un normale ciclo di richiesta/risposta è simile al seguente:

  1. Un utente richiede una pagina
  2. Dispatcher controlla se dispone già di una versione di cui è stato eseguito il rendering della pagina. Supponiamo che sia la prima richiesta per questa pagina e che Dispatcher non riesca a trovare una copia locale memorizzata nella cache.
  3. Il Dispatcher richiede la pagina dal sistema Publish
  4. Sul sistema Publish, la pagina viene riprodotta da una JSP o da un modello HTL
  5. La pagina viene restituita al Dispatcher
  6. Dispatcher memorizza nella cache la pagina
  7. Dispatcher restituisce la pagina al browser
  8. Se la stessa pagina viene richiesta una seconda volta, può essere servita direttamente dalla cache di Dispatcher senza la necessità di eseguirne nuovamente il rendering sull’istanza di Publish. Questo consente di risparmiare tempo di attesa per i cicli dell’utente e della CPU sull’istanza di Publish.

Stavamo parlando di "pagine" nell'ultima sezione. Ma lo stesso schema si applica anche ad altre risorse come immagini, file CSS, download di PDF e così via.

Memorizzazione In Cache Dei Dati

Il modulo Dispatcher sfrutta le funzionalità fornite dal server Apache che lo ospita. Risorse quali pagine di HTML, download e immagini vengono memorizzate come file semplici nel file system Apache. È così semplice.

Il nome del file è derivato dall’URL della risorsa richiesta. Se si richiede un file /foo/bar.html, questo verrà memorizzato, ad esempio, in /var/cache/docroot/foo/bar.html.

In linea di principio, se tutti i file sono memorizzati nella cache e quindi memorizzati in modo statico in Dispatcher, è possibile estrarre la spina del sistema Publish e il Dispatcher funge da semplice server web. Ma questo serve solo per illustrare il principio. La vita reale è più complicata. Non è possibile memorizzare tutto in cache e la cache non è mai completamente "piena", in quanto il numero di risorse può essere infinito a causa della natura dinamica del processo di rendering. Il modello di un file system statico consente di generare un’immagine approssimativa delle funzionalità del dispatcher. E aiuta a spiegare i limiti del dispatcher.

Struttura degli URL dell’AEM e mappatura del file system

Per comprendere il Dispatcher in modo più dettagliato, rivediamo la struttura di un semplice URL di esempio. Vediamo l’esempio seguente,

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

  • http indica il protocollo

  • domain.com è il nome di dominio

  • path/to/resource è il percorso in cui la risorsa viene archiviata in CRX e successivamente nel file system del server Apache

Da qui, le cose sono un po' diverse tra il file system dell'AEM e quello di Apache.

Nell'AEM,

  • pagename è l'etichetta delle risorse

  • selectors sta per un numero di selettori utilizzati in Sling per determinare come viene eseguito il rendering della risorsa. Un URL può avere un numero arbitrario di selettori. Sono separati da un punto. Una sezione di selettori potrebbe essere, ad esempio, simile a "french.mobile.fancy". I selettori devono contenere solo lettere, cifre e trattini.

  • html come ultimo dei "selettori" è chiamato estensione. In AEM/Sling determina anche in parte lo script di rendering.

  • path/suffix.ext è un'espressione simile a un percorso che può essere un suffisso per l'URL. Può essere utilizzato negli script AEM per controllare ulteriormente il rendering di una risorsa. In seguito verrà visualizzata un'intera sezione relativa a questa parte. Per il momento, dovrebbe essere sufficiente sapere che puoi utilizzarlo come parametro aggiuntivo. I suffissi devono avere un'estensione.

  • ?parameter=value&otherparameter=value è la sezione query dell'URL. Viene utilizzato per trasmettere parametri arbitrari all’AEM. Gli URL con parametri non possono essere memorizzati in cache e pertanto i parametri devono essere limitati ai casi in cui sono assolutamente necessari.

  • #fragment, la parte di frammento di un URL non viene passata all'AEM e viene utilizzata solo nel browser; in JavaScript funziona come "parametri di routing" o per passare a una determinata parte della pagina.

In Apache (fare riferimento al diagramma seguente),

  • pagename.selectors.html viene utilizzato come nome file nel file system della cache.

Se l'URL ha un suffisso path/suffix.ext allora,

  • pagename.selectors.html è creato come cartella

  • path una cartella nella cartella pagename.selectors.html

  • suffix.ext è un file nella cartella path. Nota: se il suffisso non ha un’estensione, il file non viene memorizzato in cache.

Layout del file system dopo aver ottenuto gli URL da Dispatcher

Layout del file system dopo aver ottenuto gli URL da Dispatcher

Limitazioni di base

La mappatura tra un URL, la risorsa e il nome del file è piuttosto semplice.

Potresti tuttavia aver notato alcune trappole,

  1. Gli URL possono diventare molto lunghi. L'aggiunta della porzione "path" di un /docroot nel file system locale potrebbe facilmente superare i limiti di alcuni file system. Eseguire Dispatcher in NTFS su Windows può essere un problema. È al sicuro con Linux, però.

  2. Gli URL possono contenere caratteri speciali e umlaut. Questo generalmente non è un problema per il dispatcher. Tuttavia, tieni presente che l’URL viene interpretato in molti punti dell’applicazione. Nella maggior parte dei casi, abbiamo assistito a strani comportamenti di un’applicazione - solo per scoprire che un pezzo di codice raramente utilizzato (personalizzato) non è stato testato completamente per i caratteri speciali. Dovresti evitarli se puoi. E se non ci riesci, pianifica dei test approfonditi.

  3. In CRX, le risorse dispongono di risorse secondarie. Ad esempio, una pagina avrà diverse sottopagine. Non è possibile trovare una corrispondenza in un file system perché i file system contengono file o cartelle.

Gli URL senza estensione non vengono memorizzati in cache

Gli URL devono sempre avere un’estensione. Anche se puoi distribuire URL senza estensioni in AEM. Questi URL non verranno memorizzati nella cache in Dispatcher.

Esempi

http://domain.com/home.html è memorizzabile in cache

http://domain.com/home è non memorizzabile in cache

La stessa regola si applica quando l’URL contiene un suffisso. Il suffisso deve avere un’estensione per essere memorizzabile in cache.

Esempi

http://domain.com/home.html/path/suffix.html è memorizzabile in cache

http://domain.com/home.html/path/suffix è non memorizzabile in cache

Potresti chiederti cosa succede se la parte risorsa non ha un’estensione, ma il suffisso ne ha una? Beh, in questo caso l’URL non ha alcun suffisso. Osserva il prossimo esempio:

Esempio

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

/home/path/suffix è il percorso della risorsa… quindi nell'URL non è presente alcun suffisso.

Conclusione

Aggiungi sempre estensioni sia al percorso che al suffisso. Le persone che sono consapevoli della SEO a volte sostengono che questa sia la classificazione dell’utente tra i risultati della ricerca. Tuttavia, una pagina non memorizzata nella cache sarebbe super lenta e sarebbe ulteriormente ridotta.

URL suffisso in conflitto

Considera di disporre di due URL validi

http://domain.com/home.html

e

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

Sono assolutamente validi nell'AEM. Non vedrai alcun problema sul tuo computer di sviluppo locale (senza un Dispatcher). Molto probabilmente non incontrerai alcun problema nei test UAT o di carico. Il problema che stiamo affrontando è così sottile che passa attraverso la maggior parte dei test. Ti colpirà duramente quando sei al momento di picco e hai un tempo limitato per affrontarlo, probabilmente non hai accesso al server e non disponi di risorse per correggerlo. Siamo stati lì…

Allora… qual è il problema?

home.html in un file system può essere un file o una cartella. Non entrambi contemporaneamente all’AEM.

Se prima richiedi home.html, verrà creato come file.

Le richieste successive a home.html/suffix.html restituiscono risultati validi, ma poiché il file home.html "blocca" la posizione nel file system, home.html non può essere creato una seconda volta come cartella e pertanto home.html/suffix.html non è memorizzato nella cache.

Posizione di blocco dei file nel file system che impedisce la memorizzazione nella cache delle risorse secondarie

Posizione di blocco dei file nel file system che impedisce la memorizzazione nella cache delle risorse secondarie

Se si esegue questa operazione al contrario, richiedendo prima home.html/suffix.html, suffix.html viene memorizzato nella cache in una cartella /home.html. Tuttavia, questa cartella viene eliminata e sostituita da un file home.html quando successivamente si richiede home.html come risorsa.

Eliminazione di una struttura di percorso quando un elemento padre viene recuperato come risorsa

Eliminazione di una struttura di percorso quando un elemento padre viene recuperato come risorsa

Pertanto, il risultato di ciò che viene memorizzato in cache è completamente casuale e dipende dall’ordine delle richieste in arrivo. Ciò che rende le cose ancora più complicate è il fatto che di solito si ha più di un dispatcher. Inoltre, le prestazioni, il tasso di hit della cache e il comportamento potrebbero variare in modo diverso da un Dispatcher all’altro. Se vuoi scoprire perché il tuo sito web non risponde, devi assicurarti di guardare il Dispatcher corretto con lo sfortunato ordine di memorizzazione in cache. Se stai cercando il Dispatcher che - per fortuna - aveva un modello di richiesta più favorevole, andrai perso nel tentativo di trovare il problema.

Evitare URL in conflitto

È possibile evitare "URL in conflitto", in cui il nome di una cartella e il nome di un file "competono" per lo stesso percorso nel file system, quando si utilizza un’estensione diversa per la risorsa quando si dispone di un suffisso.

Esempio

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

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

Entrambi sono perfettamente memorizzabili nella cache,

Scegliere un’estensione dedicata "dir" per una risorsa quando si richiede un suffisso o si evita completamente di utilizzarlo. Ci sono rari casi in cui sono utili. Ed è facile implementare questi casi correttamente. Come vedremo nel prossimo capitolo, quando si parla di invalidamento e scaricamento della cache.

Richieste non memorizzabili in cache

Esaminiamo un breve riepilogo dell’ultimo capitolo, oltre ad altre eccezioni. Dispatcher può memorizzare in cache un URL se è configurato come memorizzabile in cache e se si tratta di una richiesta GET. Non può essere memorizzato nella cache in una delle seguenti eccezioni.

Richieste memorizzabili in cache

  • La richiesta è configurata per essere memorizzabile in cache nella configurazione Dispatcher
  • La richiesta è una semplice richiesta GET

Richieste o risposte non memorizzabili nella cache

  • Richiesta negata nella cache dalla configurazione (percorso, modello, tipo MIME)
  • Risposte che restituisce un’intestazione "Dispatcher: no-cache"
  • Risposta che restituisce un’intestazione "Cache-Control: no-cache|private"
  • Risposta che restituisce un’intestazione "Pragma: no-cache"
  • Richiesta con parametri di query
  • URL senza estensione
  • URL con suffisso senza estensione
  • Risposta che restituisce un codice di stato diverso da 200
  • Richiesta POST