Uso di sottodomini per asset statici in Drupal

 

La volta scorsa, nel parlare di ottimizzazione del frontend di siti generici (e Drupal in particolare) avevamo
affrontato alcune delle problematiche principali, tra cui appunto la generazione di sottodomini per lo smistamento degli asset statici [1], così da parallelizzare il più possibile il caricamento della pagina.

Ora vedremo come ottimizzare e mettere in pratica i suggerimenti che YSlow (ma anche PageSpeed) ci danno.

NOTA: con il nome di assett intendendo con questo nome quelle informazioni che non variano o variano molto poco nel corso del tempo e che consideriamo opportuno far gestire su sottodomini differenti per ottimizzare le performance del frontend per gli utenti finali (ed eventualmente per suddividere la gestione di questo tipo di dati ai server).

Innanzitutto, andando a spulciare per bene all'interno dei suggerimento che i due strumenti prima indicati ci danno, vediamo che uno di quelli offerti è appunto la creazione di sottodomini per lo smistamento degli asset statici, questo può essere fatto comidamente andando a agire su tre elementi fondamentali:

  • CSS
  • JS
  • Immagini

I primi due possono essere spopstati su sottodomini differenti andando ad inserire un paio di semplici righe all'interno del file template.php del nostro tema, nello specifico è necesario aggiungere:

<?php
/*
* Implementation of template_preprocess_page().
*
* @param &$variables
*   Array containing various page elements.
*/
function NOOMETEMA_preprocess_page(&$variables) {
 
$static_assets_path = 'http://sottodominio.dominio.it';

  // Sostituisco negli style
 
$variables['styles'] = str_replace(' href="/sites/', ' href="' . $static_assets_path . '/sites/');
 
// Sostituisco nei JS
 
$variables['scripts'] = str_replace(' src="/sites/', ' src="' $static_assets_path . '/sites/');
}
?>

mentre per le immagini la cosa è leggermente più complessa.

Potremmo effettuare, come nel caso dei CSS e JS, una ricerca e sostituzione nella pagina, ma non è la soluzione migliore e sopratutto più performante, dato che parsare con espressionii regolari il content della pagina non è una buona soluzione, inoltre potremmo usare anche singoli campi e quindi a loro volta tutti questi dovrebbero essere parsati.

Parto dal presupposto che stiamo facendo un uso intelligente degli strumenti che Drupal ci propone, quindi quasi sicuramente staremo usanndo imagecache per la generazioni delle immagini dei diversi formati, proprio per questo baseremo le nostre funzionalità sull'estensione di questo modulo che permette di andare a indicare il sottodominio da utilizzare per le immagini generate.

Per effettuare questa modifica dobbiamo patchare il modulo in questione (per lo meno fino a che non approveranno la patch che ho inviato). L'operazione è abbastanza semplice, una volta scaricato il file allegato lanciamo:

patch -p0 < imagecache_ui.module.patch
patch -p0 < imagecache_ui.pages.inc.patch
patch -p0 < imagecache.module.patch

Fatta questa modifica, accedendo al nostro pannello di admin, come visibile qui sotto, potremmo settare i diversi sottodomini da utilizzare per lo smistamento
delle immagini; ovviamente vi consiglio di esagerare per non rendere vano il tutto a causa del delay nella risoluzione del dominio da parte dei DNS, per evitare questo attualmente ho limitato la gestione a tre sottodomini massimi, ma volendo è possibile incrementarla modificando il numero massimo di sottodomini gestibili modificando la dichiarazione della costante IMAGECACHE_MAX_SUBDOMAIN; sono indeciso se aggiungere questo dato come configurabile, cosa ne dite?

Interfaccia di configurazione dei sottodomini

A questo punto le richieste degli asset statici verranno reindirizzate sui sottodomini indicati, ma purtroppo, se andiamo ad analizzare più a fondo vedremo anche che le richieste non sono cookieless, quindi le chiamate si moltiplicano, ciò ovviamente non va per nulla bene, quindi andiamo a settare il nostro $cookie_domain
nel setting.php. La cosa che ci verrebbe naturale impostare è .www.miodominio.it in modo da non includere i diversi sottodomini. Purtroppo all'interno del file di boostrap di Drupal, il www iniziale viene rimosso, un semplice trucco è quello di andare a raddoppiarlo, quindi nel settings.php avremo:

<?php
$cookies_domain
= '.www.www.miodominio.it';
?>

in questo modo il primo verrà rimosso, mentre il secondo resterà settato. Questo permetterà di non effettuare la chiamata degli assets passando anche i cookies e quindi generando chiamate inutili (che rallentano il caricamento dei contenuti).

Potete provare a lanciare il test (ovviamente dopo aver fatto puntare anche i DNS dei sottodomini e esservi assicurati che si siano propagati) usando alcuni tools come:

AllegatoDimensione
imagecache.module.patch2.31 KB
imagecache_ui.module.patch978 byte
imagecache_ui.pages_.inc_.patch3.38 KB

Commenti

Ritratto di Anonimo

Se ho capito bene, la patch

Se ho capito bene, la patch gestisce solo il redirezionamento delle chiamate per le immagini sui subdomain. Come risolvi il problema di mettere sui sottodomini le immagini generate da imagecache? Ricordo di aver letto qualche tempo fa un articolo in proposito sul Planet, ma mi sembrava tutto molto tenuto insieme con la colla.

Ritratto di mavimo

Diverse soluzioni

Ci sono diverse soluzioni possibili che dipendono da dove sono veramente questi file. Il caso più semplice è che i domini puntino allo stesso server e non siano altro che alias dello stesso dominio. Questo di per se non scarica il server di invio immagini (magari in un prossimo articolo vedo di postare un pò di grafici di monitoraggio per spiegare perché conviene farlo), ma velocizza comunque il caricamento da parte del client.

Altra possibilità è quella di avere uno spazio condiviso tra i server dove vengono caricate le immagini e quelle dove vengono servite, però qui poi sorgono altri problemi. Innanzitutto la configurazione dello sharing (NFS o OCFS2) che non è proprio una cosa banale e richiede di avere accesso completo al server; inoltre se le richieste finiscono sulla macchia secondaria e non esistono i file generati da imagecache le richieste devono andare alla macchina principale che le genera e le salva (qui ce la si cava con un pò di regole nell'.htaccess e un file php o simili molto banale). Anche questa non è una soluzione ottimale perché comunque l'onere computazionale di generazione delle immagini resta a carico del webserver, ma comunque non è così pesante da gestire essendo comunque generato una tantum.

Altra alternativa (ed è quella che ho usato io), è di avere sulle macchine che forniscono le immagini, oltre che le immagini principali condivise, un installazione di Drupal con imagecache, ma con una patch che preleva le impostazioni di imagecache dal DB del sito principale (per mantenere l'allineamento delle configurazioni).

Poi esistono altre possibilità che sto analizzando per rendere più performante la generazione e restituzione dei dati, ma sono solo idee nella mia mente e non le ho ancora testate e analizzate :)

Ritratto di Anonimo

Alternative al patching

Prima il codice:
nb. "waffles" è il nome del tema

<?php
function waffles_imagecache($namespace, $path, $alt = '', $title = '', $attributes = NULL) {
  if (
$image = image_get_info(imagecache_create_path($namespace, $path))) {
   
$attributes['width'] = $image['width'];
   
$attributes['height'] = $image['height'];
  }
 
// check is_null so people can intentionally pass an empty array of attributes to override
  // the defaults completely... if
 
if (is_null($attributes)) {
   
$attributes['class'] = 'imagecache imagecache-'. $namespace;
  }
 
$attributes = drupal_attributes($attributes);
 
$imagecache_url = waffles_imagecache_create_url($namespace, $path);
  return
'<img src="'. $imagecache_url .'" alt="'. check_plain($alt) .'" title="'. check_plain($title) .'" '. $attributes .' />';
}

function

waffles_imagecache_create_url($presetname, $filepath, $bypass_browser_cache = FALSE) {
   
$path = _imagecache_strip_file_directory($filepath);
   
$args = array('absolute' => TRUE, 'query' => $bypass_browser_cache ? time() : $bypass_browser_cache);
    switch (
variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
        case
FILE_DOWNLOADS_PUBLIC:
           
$host = variable_get('image_url', $GLOBALS['base_url']); // : $GLOBALS['base_url'];
           
return url($host . '/' . file_directory_path() .'/imagecache/'. $presetname .'/'. $path, $args);
        case
FILE_DOWNLOADS_PRIVATE:
            return
url('system/files/imagecache/'. $presetname .'/'. $path, $args);
    }
}
?>

In pratica ridefinisco theme_imagecache per poter usare una funzione mia
waffles_imagecache_create_url
dove genero la url della immagine.

La variabile che prendo con
variable_get('image_url', $GLOBALS['base_url']); // : $GLOBALS['base_url'];
è definita nel file settings.php

Diciamo che si potrebbe pensare di fare una interfaccia amministrativa per la gestione del tutto...

ps. GRANDE TRUCCO quello finale :-)

Ritratto di mavimo

vedo se riciclando la tua

vedo se riciclando la tua ideuccia riesco a renderlo un modulo indipendente al di fuori di imagecache i modo da non rendere necessario il patching (ne la sua approvazione).

Invia nuovo commento





  • Elementi HTML permessi: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <h2> <h3> <h4>
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • Linee e paragrafi vanno a capo automaticamente.
  • Indirizzi web o e-mail vengono trasformati in link automaticamente

Maggiori informazioni sulle opzioni di formattazione.



Condividi contenuti