Nel 1999 viene stilato l'RFC 2616 contenente le specifiche per il protocollo HTTP 1.1 che introduce un gran numero di novità rispetto al predecessore. Tra queste anche la possibilità di trasferire i contenuti tra il server e il client attraverso un sistema di encoding. Questa possibilità è sfruttata fin dalla versione 1.3 di Apache tramite il mod_gzip
e oggi per mezzo del mod_deflate
.
Questi moduli agiscono in una maniera concettualmente molto semplice: se il client (browser) si dichiara capace di accettare contenuti compressi in Gzip, il server comprime il file da restituire al client e lo trasferisce in questo formato. Il client poi, prima di mostrarlo, lo decomprimerà ottenendo così il file originale.
L'idea di fondo è semplice e geniale allo stesso tempo: dato che i Pc moderni possiedono grandi capacità di calcolo e che la banda è una risorsa molto preziosa, si sacrifica una piccola porzione delle risorse di sistema (in genere i documenti passati tramite Gzip tra server e client non superano i 100Kb) per ottenere un risparmio di banda considerevole (fino all'80% con documenti di tipo testuale).
Perché questo sistema funzioni è necessario che sia il browser sia il server siano compatibili con il tipo di compressione: il mod_deflate
conferisce questa funzionalità ad Apache. Per quanto riguarda i browser invece praticamente tutti quelli moderni (da IE 4 e Netscape 3) sono in grado di gestirli (alcuni browser moderni presentano però dei bug che vedremo in seguito).
Da notare infine che il mod_deflate
non può fare miracoli: un contenuto già compresso come un'immagine in formato Jpeg o Gif o un video Mpeg non può essere compresso ulteriormente e la loro (ri)compressione può generare dei problemi ai browser riceventi.
Infine è necessario specificare che lo stesso effetto si può ottenere con i singoli linguaggi di programmazione capaci di interfacciarsi con le librerie Gzip: ad esempio per il PHP esistono specifiche soluzioni da applicare quando non si possa mettere mano direttamente alla configurazione di Apache o quando si voglia avere certezza del risultato su ogni sistema.
Come attivarlo
Ipotizzando di avere già il modulo compilato in maniera statica o in maniera dinamica l'attivazione consiste nell'indicare il mod_deflate
come filtro di output tramite cui transiteranno i vari contenuti inviati dal server:
SetOutputFilter DEFLATE
In questo caso sarà necessario specificare espressamente i tipi di file da non comprimere complicando un po' le cose. Per questo preferisco specificare espressamente i tipi di file su cui attivare il mod_deflate
tramite questo tipo di configurazione:
# AddOutputFilterByType DEFLATE mime type
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain text/xml
Nel caso in cui vogliate attivare la compressione per tutti i tipi di file esclusi alcuni da specificare (situazione che sconsiglio) è possibile inibire il mod_deflate
nel seguente modo:
SetEnvIfNoCase Request_URI (gif|jpe?g|png|pdf)$ no-gzip
È possibile inoltre attivare la registrazione nei file di log di specifici parametri legati al mod_deflate
tramite la configurazione di Apache. Possiamo infatti registrare il peso in byte che avrebbe avuto il file non compresso, il peso dello stesso compresso e il tasso di compressione applicata sul file (valore più basso corrisponde a compressione maggiore).
Si può accedere ai tre valori dopo averli resi disponibili tramite la direttiva DeflateFilterNote
rispettivamente nel seguente modo:
DeflateFilterNote Input instream DeflateFilterNote Output outstream DeflateFilterNote Ratio ratio
A questo punto instream
, outstream
e ratio
saranno le variabili contenenti i nostri dati e le potremo utilizzare tramite i file di log personalizzati in questo modo:
LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate CustomLog deflate_log_file deflate
La configurazione dettagliata dei parametri
Per configurare finemente il nostro mod_deflate
(dopo aver deciso i file su cui applicare la compressione) possiamo intervenire su quattro parametri diversi:
- DeflateBufferSize: specifica la quantità di memoria occupata da ogni frammento da comprimere. Il valore di default (quello specificato più avanti) va più che bene.
- DeflateCompressionLevel: un valore da 1 a 9 che specifica il livello di compressione. Più è alto questo livello maggiore sarà la compressione ma al tempo stesso maggiore sarà l'uso delle risorse di sistema. Per sistemi potenti e con un numero non eccessivo di visitatori si può impostare al massimo.
- DeflateMemLevel: un valore compreso tra 1 e 9 indica quanto spazio in Ram occupare per la compressione. Il valore di default di 9 è ottimo a meno di un numero molto alto di richieste al server che comunque andrà a incidere prima su altri parametri.
- DeflateWindowSize: un valore compreso tra 1 e 15 indica un altro tipo di livello di compressione. Anche qui il valore di default di 15 (maggiore compressione) è perfetto.
I possibili problemi
Come abbiamo già visto talvolta la compressione di contenuti non testuali genera problemi ad alcuni client causando nella migliore delle ipotesi una errata visualizzazione del contenuto e nella peggiore delle ipotesi un crash. Se consideriamo poi come questa compressione non porti alcun vantaggio dal punto di vista del risparmio di banda e come possa occupare molte risorse di sistema per via della dimensione dei file non testuali possiamo ben capire come non convengo attivare il mod_deflate
per questi file. Per fortuna abbiamo la possibilità di specificare i mime/type dei file su cui applicare la compressione per evitare di agire inutilmente: a questo proposito faremo in modo da far comprimere unicamente i file di tipo testuale.
Problema diverso è invece quello riscontrato con i file PDF compressi inviati ad Internet Explorer 5.5 e 6.0 con plugin Adobe per la lettura. In questo caso infatti è possibile che il sistema vada in crash. A questo proposito faremo in modo da non permettere ai file PDF di essere compressi da Apache.
È necessario inoltre tener presente che alcuni browser potrebbero dichiararsi capaci di gestire questi contenuti non essendolo realmente. Anche in questo caso possiamo avvalerci di altri moduli di Apache per modulare il file di configurazione in modo che li riconosca. Per ultimo bisogna far attenzione ad eventuali proxy attraverso cui possono transitare i dati e che potrebbero alterare gli header rendendo la fruizione reale dei contenuti diversa da quella attesa.
La configurazione definitiva
In definitiva un file di configurazione di questo tipo è perfetto per l'uso generico e permette di non avere problemi con la quasi totalità degli utenti.
<IfModule mod_deflate.c> # Specifico i file su cui applicare la compressione AddOutputFilterByType DEFLATE text/html text/plain text/xml AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE text/css # Elimino eventuali problemi derivanti dai browser # con problemi di gestione BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4.0[678] no-gzip BrowserMatch bMSI[E] !no-gzip !gzip-only-text/html # Specifico espressamente i vari livelli di compressione DeflateCompressionLevel 9 DeflateMemLevel 9 DeflateWindowSize 15 DeflateBufferSize 8096 # Mi assicuro che i proxy non creino problemi Header append Vary User-Agent env=!dont-vary # Creo il file di log contenente il tasso di compressione DeflateFilterNote ratio LogFormat "%v %h %l %u %t "%r" %>s %b mod_deflate: %{deflate_ratio}n pct." deflate_vhost CustomLog logs/deflate.log deflate_vhost </IfModule>
Installate questo modulo sul vostro server di produzione e vedrete veramente crollare l'impiego di banda. Considerando il caching delle immagini attuato dai browser moderni infatti il traffico dovuto ai file testuali (prevalentemente HTML) acquista un peso relativo decisamente rilevante nel complesso dei file trasferiti.